CMD+] indent and CMD+[ deindent - javascript

I have the following code to indent a tab.
$('#submit-content').keydown(function(e) {
var keyCode = e.keyCode || e.which;
if (keyCode == 9 || e.metaKey && keyCode == 221) {
e.preventDefault();
var start = $(this).get(0).selectionStart;
var end = $(this).get(0).selectionEnd;
// set textarea value to: text before caret + tab + text after caret
$(this).val($(this).val().substring(0, start)
+ "\t"
+ $(this).val().substring(end));
// put caret at right position again
$(this).get(0).selectionStart =
$(this).get(0).selectionEnd = start + 1;
}
I want to alter this code to de-indent.
I tried -"\t" but it wont work as expected

Related

Textarea loses focus when calling a function

What I'm trying to achieve is to read the current word at the caret position.
Example:
Hello| -> returns Hello
Hel|lo -> returns Hello
I have put the code inside an event handler which is onKeyup inside an if statement:
if( e.keyCode === 37 || e.keyCode === 39 ){
console.log($(this).getWord());
}
When this is executed, it returns the current word, but the text area loses the focus.
Jsfiddle
How is this supposed to work?
Type word in the text area then click on left or right arrow keys, the current word will get displayed.
I would use textArea.selectionStart instead of mucking with mutating the selection itself. This will work for you if Internet Exploder < 8 compatibility isn't a concern.
var $mytextarea = $('#mytextarea');
$mytextarea.keyup(function(e) {
if (e.keyCode === 37 || e.keyCode === 39) {
$("#current").text(getWord());
}
});
function getWord() {
var textarea = $mytextarea[0],
pos = textarea.selectionStart,
raw = textarea.value,
start = pos,
end = pos;
while (raw.charAt(start) !== ' ' && start > 0) {
start--;
}
while (raw.charAt(end) !== ' ' && end < raw.length) {
end++;
}
return raw.substring(start, end);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="mytextarea">The quick brown fox jumps over the lazy dog.</textarea>
<div>
the current word is <span id="current"></span>
</div>
I changed your code a bit. It no longer manipulates the cursor which means response time is a lot faster.
Here is your updated code:
$('#mytextarea').keyup(function (e) {
//if (e.keyCode === 37 || e.keyCode === 39) {
//get cursor position
var caret = getCaretPosition(this);
//get the end index of current word
var endOfWord = this.value.slice(caret.end).match(/(\s|$)/i).index + caret.end;
//get current word
var word = /\S+$/.exec(this.value.slice(0,endOfWord));
//make sure word is not null
word = word ? word[0] : '';
//remove punctuation
word = word.replace(/(\.|\!|,|;|:|\(|\)|\{|\}|\[|\]|'|"|-$)/,'');
$("#current").text(word);
//}
});
function getCaretPosition(ctrl) {
var start, end;
if (ctrl.setSelectionRange) {
start = ctrl.selectionStart;
end = ctrl.selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
start = 0 - range.duplicate().moveStart('character', -100000);
end = start + range.text.length;
}
return {
start: start,
end: end
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="mytextarea"></textarea>
<div>
the current word is <span id="current"></span>
</div>
I do want to point out this is not my code and was copied from this fiddle.

Jquery Auto change focused text box via button

i am creating a system where there will be a pacific mobile view. From this you will be able to press one of 3 buttons and it will emulate a key press on a keyboard.
Currently for the desktop version the focused box changes like this:
$('.today').keydown(function(e) {
if ($.inArray(e.keyCode, [69, 88, 191, 8, 40, 38]) === -1) { // 8 is backspace
e.preventDefault();
}
});
$('.today').keyup(function(e) {
if ($.inArray(e.keyCode, [69, 88, 191, 8, 40, 38]) === -1) { // e, x, / respectively // don't print the character
return false;
}
var self = $(this);
var currentInput = self.data('number');
var next = $(currentInput + 1);
var previous = $(currentInput - 1);
var keyCode = e.keyCode || e.which;
var num = self.data('number') + 1;
var nom = self.data('number') - 1;
if(('input.today[data-number="' + num +'"]').length && keyCode === 40)
$('input.today[data-number="' + num +'"]').focus()
else if(('input.today[data-number="' + nom +'"]').length && keyCode === 38)
$('input.today[data-number="' + nom +'"]').focus();
else if(('input.today[data-number="' + num +'"]').length && self.val().length == self.attr('size')) {
$('input.today[data-number="' + num +'"]').focus();
}
});
For the buttons I have this piece of code:
$("button").click(function() {
$(".today").focus();
var e = jQuery.Event("keydown");
e.which = 47; // # Some key code value
$("input").val(String.fromCharCode(e.which));
$("input").trigger(e);
});
$('input').keypress(function(e){
console.log('Yes keydown triggered. ' + e.which)
});
This fills the text box and it will change to next, but then when i press it will focus back to original... Any ideas.
$(".today").focus();
suggests your using classes as the identifier, are your ID's unique?

Capitalize first letter of words in sentence, except on manual replacement

I have an input field that the user will fill in and I want to automatically capitalize the first letter of each word as they're typing. However, if they manually delete a capital letter and replace it with a lower case, I want that to remain (basically capitalizing the letters is what we recommend, but not required). I'm having trouble implementing something that will leave the letters they manually typed alone and not change them.
Here is the code I have along with a Jsfiddle link to it.
<input class="capitalize" />
and JS:
lastClick = 0;
$(document).ready(function() {
$(".capitalize").keyup(function() {
var key = event.keyCode || event.charCode;
if (!(lastClick == 8 || lastClick == 46)) {
//checks if last click was delete or backspace
str = $(this).val();
//Replace first letter of each word with upper-case version.
$(this).val(str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();}));
}
lastClick = key;
});
});
I haven't allowed for preserving the user's manual corrections, but as it is you can see in the jsfiddle that the input jumps around and doesn't work correctly. Can anyone help me or recommend a best way to do this? Thank you.
$(document).ready(function() {
var last;
$(".capitalize").on('keyup', function(event) {
var key = event.keyCode || event.which,
pos = this.value.length,
value = this.value;
if (pos == 1 || last == 32 && (last !== 8 || last !== 46)) {
this.value = value.substring(0, pos - 1) +
value.substring(pos - 1).toUpperCase();
}
last = key;
});
});
http://jsfiddle.net/userdude/tsUnH/1
$(document).ready(function() {
$(".capitalize")
.keyup(function(event) {
var key = event.keyCode || event.charCode;
// store the key which was just pressed
$(this).data('last-key', key);
})
.keypress(function(event) {
var key = event.keyCode || event.charCode;
var lastKey = $(this).data('last-key') ? $(this).data('last-key') : 0; // we store the previous action
var $this = $(this); // local reference to the text input
var str = $this.val(); // local copy of what our value is
var pos = str.length;
if(null !== String.fromCharCode(event.which).match(/[a-z]/g)) {
if ((pos == 0 || str.substr(pos - 1) == " ") && (!(lastKey == 8 || lastKey == 46))) {
event.preventDefault();
$this.val($this.val() + String.fromCharCode(event.which).toUpperCase());
}
}
// store the key which was just pressed
$(this).data('last-key', key);
});
});
I have updated your fiddle http://jsfiddle.net/nB4cj/4/ which will show this working.

Can I return a string into an input type: text field onkeypress?

I have a sentence defined as a list(a string? an array?- I'm not sure the correct term) that I want returned sequentially as any key is pressed. I'm trying to use .split. Here is the list and function:
var list1 = "This is a test".replace(/\s/g, "\xA0").split("")
function transformTypedChar(charStr) {
var position = $("#verse1").text().length;
if (position >= list1.length) return '';
else return list1[position];
}
Currently, the "T" from the beginning of the list is returned repeatedly, and the rest of the list is ignored. I'm calling the function as follows:
document.getElementById("verse1").onkeypress = function(evt) {
var val = this.value;
evt = evt || window.event;
// Ensure we only handle printable keys, excluding enter and space
var charCode = typeof evt.which == "number" ? evt.which : evt.keyCode;
if (charCode && charCode > 32) {
var keyChar = String.fromCharCode(charCode);
// Transform typed character
var mappedChar = transformTypedChar(keyChar);
var start, end;
if (typeof this.selectionStart == "number" && typeof this.selectionEnd ==
"number") {
// Non-IE browsers and IE 9
start = this.selectionStart;
end = this.selectionEnd;
this.value = val.slice(0, start) + mappedChar + val.slice(end);
// Move the caret
this.selectionStart = this.selectionEnd = start + 1;
} else if (document.selection && document.selection.createRange) {
// For IE up to version 8
var selectionRange = document.selection.createRange();
var textInputRange = this.createTextRange();
var precedingRange = this.createTextRange();
var bookmark = selectionRange.getBookmark();
textInputRange.moveToBookmark(bookmark);
precedingRange.setEndPoint("EndToStart", textInputRange);
start = precedingRange.text.length;
end = start + selectionRange.text.length;
this.value = val.slice(0, start) + mappedChar + val.slice(end);
start++;
// Move the caret
textInputRange = this.createTextRange();
textInputRange.collapse(true);
textInputRange.move("character", start - (this.value.slice(0,
start).split("\r\n").length - 1));
textInputRange.select();
}
return false;
}
};
How do I return the entire list, sequentially? In other words, on the first key event the "T" appears, on the second key event, the "h" appears and so on. I can achieve this in contenteditable divs, but I'm using input type: text fields as I want to autotab between.
The entire code is here: http://jsfiddle.net/NAC77/9/
Calling $(el).text() on input elements returns an empty string, you should be calling $(el).val(): http://jsfiddle.net/NAC77/10/

How to handle <tab> in textarea?

I would like a textarea that handles a situation of pressing tab key.
In default case if you press a tab key then focus leaves the textarea. But what about the situation when user wants to type tab key in textarea?
Can I catch this event and return focus to the textarea and add a tab to a current cursor position?
You can: http://jsfiddle.net/sdDVf/8/.
$("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();
}
});
Here is a modified version of pimvdb's answer that doesn't need JQuery:
document.querySelector("textarea").addEventListener('keydown',function(e) {
if(e.keyCode === 9) { // tab was pressed
// get caret position/selection
var start = this.selectionStart;
var end = this.selectionEnd;
var target = e.target;
var value = target.value;
// set textarea value to: text before caret + tab + text after caret
target.value = 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();
}
},false);
I tested it in Firefox 21.0 and Chrome 27. Don't know if it works anywhere else.
Good god, all previous answers failed to provide the commonly decent (i.e. for programmers) tab control.
That is, a hitting TAB on selection of lines will indent those lines, and SHIFTTAB will un-indent them.
_edited (Nov 2016): keyCode replaced with charCode || keyCode, per KeyboardEvent.charCode - Web APIs | MDN
(function($) {
$.fn.enableSmartTab = function() {
var $this;
$this = $(this);
$this.keydown(function(e) {
var after, before, end, lastNewLine, changeLength, re, replace, selection, start, val;
if ((e.charCode === 9 || e.keyCode === 9) && !e.altKey && !e.ctrlKey && !e.metaKey) {
e.preventDefault();
start = this.selectionStart;
end = this.selectionEnd;
val = $this.val();
before = val.substring(0, start);
after = val.substring(end);
replace = true;
if (start !== end) {
selection = val.substring(start, end);
if (~selection.indexOf('\n')) {
replace = false;
changeLength = 0;
lastNewLine = before.lastIndexOf('\n');
if (!~lastNewLine) {
selection = before + selection;
changeLength = before.length;
before = '';
} else {
selection = before.substring(lastNewLine) + selection;
changeLength = before.length - lastNewLine;
before = before.substring(0, lastNewLine);
}
if (e.shiftKey) {
re = /(\n|^)(\t|[ ]{1,8})/g;
if (selection.match(re)) {
start--;
changeLength--;
}
selection = selection.replace(re, '$1');
} else {
selection = selection.replace(/(\n|^)/g, '$1\t');
start++;
changeLength++;
}
$this.val(before + selection + after);
this.selectionStart = start;
this.selectionEnd = start + selection.length - changeLength;
}
}
if (replace && !e.shiftKey) {
$this.val(before + '\t' + after);
this.selectionStart = this.selectionEnd = start + 1;
}
}
});
};
})(jQuery);
$(function() {
$("textarea").enableSmartTab();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="10" cols="80">
/* Just some code to edit with our new superTab */
(function($) {
$.fn.enableSmartTab = function() {
$this = $(this);
$this.keydown(function(e) {
if ((e.charCode === 9 || e.keyCode === 9) && !e.metaKey && !e.ctrlKey && !e.altKey) {
e.preventDefault();
}
}
}
}
</textarea>
In Vanilla (Default) JS this would be:
var textareas = document.getElementsByTagName('textarea');
if ( textareas ) {
for ( var i = 0; i < textareas.length; i++ ) {
textareas[i].addEventListener( 'keydown', function ( e ) {
if ( e.which != 9 ) return;
var start = this.selectionStart;
var end = this.selectionEnd;
this.value = this.value.substr( 0, start ) + "\t" + this.value.substr( end );
this.selectionStart = this.selectionEnd = start + 1;
e.preventDefault();
return false;
});
}
}
textarea {
border: 1px solid #cfcfcf;
width: 100%;
margin-left: 0px;
top: 0px;
bottom: 0px;
position: absolute;
}
<textarea>
var x = 10;
var y = 10;
</textarea>
Found this while searching google. I made a really short one that can also indent and reverse indent selections of text:
jQ(document).on('keydown', 'textarea', function(e) {
if (e.keyCode !== 9) return;
var Z;
var S = this.selectionStart;
var E = Z = this.selectionEnd;
var A = this.value.slice(S, E);
A = A.split('\n');
if (!e.shiftKey)
for (var x in A) {
A[x] = '\t' + A[x];
Z++;
}
else
for (var x in A) {
if (A[x][0] == '\t')
A[x] = A[x].substr(1);
Z--;
}
A = A.join('\n');
this.value = this.value.slice(0, S) + A + this.value.slice(E);
this.selectionStart = S != E ? S : Z;;
this.selectionEnd = Z;
e.preventDefault();
});
Enable tabbing inside (multiple) textarea elements
Correcting #alexwells answer and enable a live demo
var textAreaArray = document.querySelectorAll("textarea");
for (var i = textAreaArray.length-1; i >=0;i--){
textAreaArray[i].addEventListener('keydown',function(e) {
if(e.keyCode === 9) { // tab was pressed
// get caret position/selection
var start = this.selectionStart;
var end = this.selectionEnd;
var target = e.target;
var value = target.value;
// set textarea value to: text before caret + tab + text after caret
target.value = 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();
}
},false);
}
<textarea rows="10" cols="80"></textarea>
<textarea rows="10" cols="80"></textarea>

Categories