How do I highlight and change a part of a textarea - javascript

I have a textarea where when the user selects and presses enter I want it to change to something else. For example I have a textarea, when a user selects something like NY, I want those two letters to change to NY
Here's a fiddle but I'm lost
I have something like :
$('textarea').html('I live in NY and it\'s a great place to live');
$(window).click(function(){
var selection = selectedText();
console.log(selection);
});
function selectedText() {
var ret = '';
if (window.getSelection){
ret = window.getSelection();
} else if (document.getSelection) {
ret = document.getSelection();
} else if (document.selection) {
ret = document.selection.createRange().text;
}
return ret;
}
I don't know where to check to see if it's from a textarea or from somewhere else, and I don't know how to change a specific part of a textarea's text

There are a lot of cross browser nuances when it comes to text selection. There are several jQuery plugins trying to deal with this. I'd recommend using a-tools. I've used it in the past, and it works as advertised.

This might help you :
Finding selection start and end position in a textarea
Also i just tested this and it works (it returns the selected text , so you can modify it and assign the value back to the textarea
Ref : http://www.codingforums.com/showpost.php?p=235174&postcount=5
<script type="text/javascript">
<!--//
function selectedText(input){
if(document.selection && document.selection.createRange().text != ''){ // IS IE
alert(document.selection.createRange().text);
}
else{ // Not IE.. assume Mozilla?
var startPos = input.selectionStart;
var endPos = input.selectionEnd;
alert(input.value.substring(startPos, endPos))
}
}
//-->
</script>
</head>
<body>
<form name="reportForm">
<textarea name="report">this is a test</textarea>
<button onclick="selectedText(this.form.report)">Alert Selection</button>
</form>

Related

Javascript how to place cursor at end of input field text after inserting text? [duplicate]

What is the best way (and I presume simplest way) to place the cursor at the end of the text in a input text element via JavaScript - after focus has been set to the element?
There's a simple way to get it working in most browsers.
this.selectionStart = this.selectionEnd = this.value.length;
However, due to the *quirks of a few browsers, a more inclusive answer looks more like this
setTimeout(function(){ that.selectionStart = that.selectionEnd = 10000; }, 0);
Using jQuery (to set the listener, but it's not necessary otherwise)
$('#el').focus(function(){
var that = this;
setTimeout(function(){ that.selectionStart = that.selectionEnd = 10000; }, 0);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='el' type='text' value='put cursor at end'>
Using Vanilla JS (borrowing addEvent function from this answer)
// Basic cross browser addEvent
function addEvent(elem, event, fn){
if(elem.addEventListener){
elem.addEventListener(event, fn, false);
}else{
elem.attachEvent("on" + event,
function(){ return(fn.call(elem, window.event)); });
}}
var element = document.getElementById('el');
addEvent(element,'focus',function(){
var that = this;
setTimeout(function(){ that.selectionStart = that.selectionEnd = 10000; }, 0);
});
<input id='el' type='text' value='put cursor at end'>
Quirks
Chrome has an odd quirk where the focus event fires before the cursor is moved into the field; which screws my simple solution up. Two options to fix this:
You can add a timeout of 0 ms (to defer the operation until the stack is clear)
You can change the event from focus to mouseup. This would be pretty annoying for the user unless you still kept track of focus. I'm not really in love with either of these options.
Also, #vladkras pointed out that some older versions of Opera incorrectly calculate the length when it has spaces. For this you can use a huge number that should be larger than your string.
Try this, it has worked for me:
//input is the input element
input.focus(); //sets focus to element
var val = this.input.value; //store the value of the element
this.input.value = ''; //clear the value of the element
this.input.value = val; //set that value back.
For the cursor to be move to the end, the input has to have focus first, then when the value is changed it will goto the end. If you set .value to the same, it won't change in chrome.
I faced this same issue (after setting focus through RJS/prototype) in IE.
Firefox was already leaving the cursor at the end when there is already a value for the field. IE was forcing the cursor to the beginning of the text.
The solution I arrived at is as follows:
<input id="search" type="text" value="mycurrtext" size="30"
onfocus="this.value = this.value;" name="search"/>
This works in both IE7 and FF3 but doesn't work in modern browsers (see comments) as it is not specified that UA must overwrite the value in this case (edited in accordance with meta policy).
After hacking around with this a bit, I found the best way was to use the setSelectionRange function if the browser supports it; if not, revert to using the method in Mike Berrow's answer (i.e. replace the value with itself).
I'm also setting scrollTop to a high value in case we're in a vertically-scrollable textarea. (Using an arbitrary high value seems more reliable than $(this).height() in Firefox and Chrome.)
I've made it is as a jQuery plugin. (If you're not using jQuery I trust you can still get the gist easily enough.)
I've tested in IE6, IE7, IE8, Firefox 3.5.5, Google Chrome 3.0, Safari 4.0.4, Opera 10.00.
It's available on jquery.com as the PutCursorAtEnd plugin. For your convenience, the code for release 1.0 is as follows:
// jQuery plugin: PutCursorAtEnd 1.0
// http://plugins.jquery.com/project/PutCursorAtEnd
// by teedyay
//
// Puts the cursor at the end of a textbox/ textarea
// codesnippet: 691e18b1-f4f9-41b4-8fe8-bc8ee51b48d4
(function($)
{
jQuery.fn.putCursorAtEnd = function()
{
return this.each(function()
{
$(this).focus()
// If this function exists...
if (this.setSelectionRange)
{
// ... then use it
// (Doesn't work in IE)
// Double the length because Opera is inconsistent about whether a carriage return is one character or two. Sigh.
var len = $(this).val().length * 2;
this.setSelectionRange(len, len);
}
else
{
// ... otherwise replace the contents with itself
// (Doesn't work in Google Chrome)
$(this).val($(this).val());
}
// Scroll to the bottom, in case we're in a tall textarea
// (Necessary for Firefox and Google Chrome)
this.scrollTop = 999999;
});
};
})(jQuery);
<script type="text/javascript">
function SetEnd(txt) {
if (txt.createTextRange) {
//IE
var FieldRange = txt.createTextRange();
FieldRange.moveStart('character', txt.value.length);
FieldRange.collapse();
FieldRange.select();
}
else {
//Firefox and Opera
txt.focus();
var length = txt.value.length;
txt.setSelectionRange(length, length);
}
}
</script>
This function works for me in IE9, Firefox 6.x, and Opera 11.x
It's 2019 and none of the methods above worked for me, but this one did, taken from https://css-tricks.com/snippets/javascript/move-cursor-to-end-of-input/
function moveCursorToEnd(id) {
var el = document.getElementById(id)
el.focus()
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}
<input id="myinput" type="text" />
Move cursor to end
I've tried the following with quite great success in chrome
$("input.focus").focus(function () {
var val = this.value,
$this = $(this);
$this.val("");
setTimeout(function () {
$this.val(val);
}, 1);
});
Quick rundown:
It takes every input field with the class focus on it, then stores the old value of the input field in a variable, afterwards it applies the empty string to the input field.
Then it waits 1 milisecond and puts in the old value again.
el.setSelectionRange(-1, -1);
https://codesandbox.io/s/peaceful-bash-x2mti
This method updates the HTMLInputElement.selectionStart, selectionEnd,
and selectionDirection properties in one call.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setSelectionRange
In other js methods -1 usually means (to the) last character. This is the case for this one too, but I couldn't find explicit mention of this behavior in the docs.
Simple. When editing or changing values, first put the focus then set value.
$("#catg_name").focus();
$("#catg_name").val(catg_name);
Still the intermediate variable is needed, (see var val=)
else the cursor behaves strange, we need it at the end.
<body onload="document.getElementById('userinput').focus();">
<form>
<input id="userinput" onfocus="var val=this.value; this.value=''; this.value= val;"
class=large type="text" size="10" maxlength="50" value="beans" name="myinput">
</form>
</body>
const end = input.value.length
input.setSelectionRange(end, end)
// 👇 scroll to the bottom if a textarea has long text
input.focus()
Try this one works with Vanilla JavaScript.
<input type="text" id="yourId" onfocus="let value = this.value; this.value = null; this.value=value" name="nameYouWant" class="yourClass" value="yourValue" placeholder="yourPlaceholder...">
In Js
document.getElementById("yourId").focus()
For all browsers for all cases:
function moveCursorToEnd(el) {
window.setTimeout(function () {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}, 1);
}
Timeout required if you need to move cursor from onFocus event handler
I like the accepted answer a lot, but it stopped working in Chrome. In Chrome, for the cursor to go to the end, input value needs to change. The solution is as follow:
<input id="search" type="text" value="mycurrtext" size="30"
onfocus="var value = this.value; this.value = null; this.value = value;" name="search"/>
document.querySelector('input').addEventListener('focus', e => {
const { value } = e.target;
e.target.setSelectionRange(value.length, value.length);
});
<input value="my text" />
In jQuery, that's
$(document).ready(function () {
$('input').focus(function () {
$(this).attr('value',$(this).attr('value'));
}
}
I just found that in iOS, setting textarea.textContent property will place the cursor at the end of the text in the textarea element every time. The behavior was a bug in my app, but seems to be something that you could use intentionally.
This problem is interesting. The most confusing thing about it is that no solution I found solved the problem completely.
+++++++ SOLUTION +++++++
You need a JS function, like this:
function moveCursorToEnd(obj) {
if (!(obj.updating)) {
obj.updating = true;
var oldValue = obj.value;
obj.value = '';
setTimeout(function(){ obj.value = oldValue; obj.updating = false; }, 100);
}
}
You need to call this guy in the onfocus and onclick events.
<input type="text" value="Test Field" onfocus="moveCursorToEnd(this)" onclick="moveCursorToEnd(this)">
IT WORKS ON ALL DEVICES AN BROWSERS!!!!
var valsrch = $('#search').val();
$('#search').val('').focus().val(valsrch);
Taking some of the answers .. making a single-line jquery.
$('#search').focus().val($('#search').val());
If the input field just needs a static default value I usually do this with jQuery:
$('#input').focus().val('Default value');
This seems to work in all browsers.
While this may be an old question with lots of answers, I ran across a similar issue and none of the answers were quite what I wanted and/or were poorly explained. The issue with selectionStart and selectionEnd properties is that they don't exist for input type number (while the question was asked for text type, I reckon it might help others who might have other input types that they need to focus). So if you don't know whether the input type the function will focus is a type number or not, you cannot use that solution.
The solution that works cross browser and for all input types is rather simple:
get and store the value of input in a variable
focus the input
set the value of input to the stored value
That way the cursor is at the end of the input element.
So all you'd do is something like this (using jquery, provided the element selector that one wishes to focus is accessible via 'data-focus-element' data attribute of the clicked element and the function executes after clicking on '.foo' element):
$('.foo').click(function() {
element_selector = $(this).attr('data-focus-element');
$focus = $(element_selector);
value = $focus.val();
$focus.focus();
$focus.val(value);
});
Why does this work? Simply, when the .focus() is called, the focus will be added to the beginning of the input element (which is the core problem here), ignoring the fact, that the input element already has a value in it. However, when the value of an input is changed, the cursor is automatically placed at the end of the value inside input element. So if you override the value with the same value that had been previously entered in the input, the value will look untouched, the cursor will, however, move to the end.
Super easy (you may have to focus on the input element)
inputEl = getElementById('inputId');
var temp = inputEl.value;
inputEl.value = '';
inputEl.value = temp;
Set the cursor when click on text area to the end of text...
Variation of this code is...ALSO works! for Firefox, IE, Safari, Chrome..
In server-side code:
txtAddNoteMessage.Attributes.Add("onClick", "sendCursorToEnd('" & txtAddNoteMessage.ClientID & "');")
In Javascript:
function sendCursorToEnd(obj) {
var value = $(obj).val(); //store the value of the element
var message = "";
if (value != "") {
message = value + "\n";
};
$(obj).focus().val(message);
$(obj).unbind();
}
If you set the value first and then set the focus, the cursor will always appear at the end.
$("#search-button").click(function (event) {
event.preventDefault();
$('#textbox').val('this');
$("#textbox").focus();
return false;
});
Here is the fiddle to test
https://jsfiddle.net/5on50caf/1/
I wanted to put cursor at the end of a "div" element where contenteditable = true, and I got a solution with Xeoncross code:
<input type="button" value="Paste HTML" onclick="document.getElementById('test').focus(); pasteHtmlAtCaret('<b>INSERTED</b>'); ">
<div id="test" contenteditable="true">
Here is some nice text
</div>
And this function do magic:
function pasteHtmlAtCaret(html) {
var sel, range;
if (window.getSelection) {
// IE9 and non-IE
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
range = sel.getRangeAt(0);
range.deleteContents();
// Range.createContextualFragment() would be useful here but is
// non-standard and not supported in all browsers (IE9, for one)
var el = document.createElement("div");
el.innerHTML = html;
var frag = document.createDocumentFragment(), node, lastNode;
while ( (node = el.firstChild) ) {
lastNode = frag.appendChild(node);
}
range.insertNode(frag);
// Preserve the selection
if (lastNode) {
range = range.cloneRange();
range.setStartAfter(lastNode);
range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
}
}
} else if (document.selection && document.selection.type != "Control") {
// IE < 9
document.selection.createRange().pasteHTML(html);
}
}
Works fine for most browsers, please check it, this code puts text and put focus at the end of the text in div element (not input element)
https://jsfiddle.net/Xeoncross/4tUDk/
Thanks, Xeoncross
I also faced same problem. Finally this gonna work for me:
jQuery.fn.putCursorAtEnd = = function() {
return this.each(function() {
// Cache references
var $el = $(this),
el = this;
// Only focus if input isn't already
if (!$el.is(":focus")) {
$el.focus();
}
// If this function exists... (IE 9+)
if (el.setSelectionRange) {
// Double the length because Opera is inconsistent about whether a carriage return is one character or two.
var len = $el.val().length * 2;
// Timeout seems to be required for Blink
setTimeout(function() {
el.setSelectionRange(len, len);
}, 1);
} else {
// As a fallback, replace the contents with itself
// Doesn't work in Chrome, but Chrome supports setSelectionRange
$el.val($el.val());
}
// Scroll to the bottom, in case we're in a tall textarea
// (Necessary for Firefox and Chrome)
this.scrollTop = 999999;
});
};
This is how we can call this:
var searchInput = $("#searchInputOrTextarea");
searchInput
.putCursorAtEnd() // should be chainable
.on("focus", function() { // could be on any event
searchInput.putCursorAtEnd()
});
It's works for me in safari, IE, Chrome, Mozilla. On mobile devices I didn't tried this.
Check this solution!
//fn setCurPosition
$.fn.setCurPosition = function(pos) {
this.focus();
this.each(function(index, elem) {
if (elem.setSelectionRange) {
elem.setSelectionRange(pos, pos);
} else if (elem.createTextRange) {
var range = elem.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
});
return this;
};
// USAGE - Set Cursor ends
$('#str1').setCurPosition($('#str1').val().length);
// USAGE - Set Cursor at 7 position
// $('#str2').setCurPosition(7);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Set cursor at any position</p>
<p><input type="text" id="str1" value="my string here" /></p>
<p><input type="text" id="str2" value="my string here" /></p>
I took the best answers from here, and created a function that works well in Chrome.
You will need to wrap the logic in a timeout, because you have to wait for the focus to finish before accessing the selection
To place the cursor at the end, the selection start needs to be placed at the end
In order to scroll to the end of the input field, the scrollLeft needs to match the scrollWidth
/**
* Upon focus, set the cursor to the end of the text input
* #param {HTMLInputElement} inputEl - An HTML <input> element
*/
const setFocusEnd = (inputEl) => {
setTimeout(() => {
const { scrollWidth, value: { length } } = inputEl;
inputEl.setSelectionRange(length, length);
inputEl.scrollLeft = scrollWidth;
}, 0);
};
document
.querySelector('input')
.addEventListener('focus', (e) => setFocusEnd(e.target));
html, body {
width: 100%;
height: 100%;
margin: 0;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
input:focus {
background-color: hsla(240, 100%, 95%, 1.0);
}
<input
type="text"
placeholder="Search..."
value="This is some really, really long text">
<input id="input_1">
<input id="input_2" type="hidden">
<script type="text/javascript">
//save input_1 value to input_2
$("#input_2").val($("#input_1").val());
//empty input_1 and add the saved input_2 into input_1
$("#input_1").val("").val($("#input_2").val()).focus();
</script>

Text Input Selection not working in IE9

I am trying to get the user selected text in a text input when a button is clicked. This what I am trying:
<head>
<script type="text/javascript">
function GetSelectedText () {
if (window.getSelection) { // all browsers, except IE before version 9
var range = window.getSelection ();
alert (range.toString ());
}
else {
if (document.selection.createRange) { // Internet Explorer
document.getElementById("foo").focus();
var range = document.selection.createRange();
alert (range.text);
}
}
}
</script>
</head>
<body>
<button onclick="GetSelectedText ()">Get the selected text!</button>
<input type = 'text' id = 'foo' />12345
</body>
It works as expected in all browsers, except IE9. In IE9, if you select some text from the 12345 chunk and press the button, the selected text is alerted all right. However, if you type something in the text input, select some of it, and click the button, a blank alert is generated.
Can anyone tell me how do I get it working in IE9? And is there any way to get the cursor position of the selection start as well (something like Mozilla's selectionStart)? Iam looking for Javascript solution, without Rangy or other related jQuery libraries..
Text inputs and textareas have a separate selection API, namely selectionStart and selectionEnd properties of the input itself. These are not supported in IE <= 8, but you already have the alternative for those.
Here's an implementation of your GetSelectedText() function that works in all major browsers:
Demo: http://jsfiddle.net/UK8gA/
Code:
function GetSelectedText() {
var selectedText = "";
var input = document.getElementById("foo");
var sel, val = input.value;
input.focus();
if (typeof input.selectionStart == "number") {
selectedText = val.slice(input.selectionStart, input.selectionEnd);
} else if ( (sel = document.selection) && sel.createRange) { // IE
var range = document.selection.createRange();
selectedText = range.text;
}
alert(selectedText);
}
You can take a look at the jQuery Caret plugin: jCaret
// Get start pos in intput box with id="box1"
$("#box1").caret().start
// Get end pos
$("#box1").caret().end
// Get selected text
$("#box1").caret().text
It all looks good except that the line "document.getElementById("foo").focus();" does not appear to be necessary and is probably why the browser is unable to detect the highlighted text. Try to remove it and see what you get.

In contenteditable how do you add a paragraph after blockquote on Enter key press?

I have the following problem. Once I add a blockquote in contenteditable, by pressing Enter key it moves to a new line and adds another blockquote element. It goes on forever, and I can’t escape the formatting. The desired functionality would be that of the unordered list. When you press the Enter key it adds a new empty <li> element, but if you press Enter again, it escapes the formatting, removes the previously created <li> and adds a <p>.
Check out the demo: http://jsfiddle.net/wa9pM/
One hack I found was to create an empty <p> under the blockquote, before you create a blockquote. But is there a way to break this formatting behaviour with JavaScript? No idea how I would check: if where the cursor is, it’s the end of the line and if it’s a blockquote and on Enter key press, don’t add a new blockquote.
I’m using this code to generate a blockquote in JS:
document.execCommand('formatBlock', false, 'blockquote');
While creating a rich text editor for an iOS application i faced the same problem. Every time i've inserted a <blockquote> tag in my text field and pressed Enter, it was impossible to get rid off the block-quote.
After researching a bit, i've found a working solution.
Finding inner HTML tags:
function whichTag(tagName){
var sel, containerNode;
var tagFound = false;
tagName = tagName.toUpperCase();
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
containerNode = sel.getRangeAt(0).commonAncestorContainer;
}
}else if( (sel = document.selection) && sel.type != "Control" ) {
containerNode = sel.createRange().parentElement();
}
while (containerNode) {
if (containerNode.nodeType == 1 && containerNode.tagName == tagName) {
tagFound = true;
containerNode = null;
}else{
containerNode = containerNode.parentNode;
}
}
return tagFound;
}
Checking for occurrences of the block-quote tag:
function checkBlockquote(){
var input = document.getElementById('text_field_id');
input.onkeydown = function() {
var key = event.keyCode || event.charCode;
if( key == 13){
if (whichTag("blockquote")){
document.execCommand('InsertParagraph');
document.execCommand('Outdent');
}
}
};
}
Triggering the key down events:
<body onLoad="checkBlockquote();">
<!-- stuff... -->
</body>
I believe the code above can be adjusted to fit your needs easily. If you need further help, feel free to ask.
Something like this did the work for me (at least on Chrome and Safari).
Demo at http://jsfiddle.net/XLPrw/
$("[contenteditable]").on("keypress", function(e) {
var range = window.getSelection().getRangeAt();
var element = range.commonAncestorContainer;
if(element.nodeName == "BLOCKQUOTE") {
element.parentElement.removeChild(element);
}
});
Didn't make any extensive test, but it looks like range.commonAncestorElement returns the current textnode in case the blockquote contains text, or the blockquote element itself in case it contains no textnode (on Chrome, a <br> is added and caret is positioned after it). You can remove the newly created blockquote in this case. Anyway, after deleting the element the caret looks like getting positioned somewhere upon the contenteditable, although typing confirms that it's right after the original blackquote.
Hope this points you to a more conclusive solution.
Super late answer, but this was a much simpler solution for me. Hopefully it helps anyone else looking. Browser compatibility may vary.
YOUR_EDITABLE_ELEMENT.addEventListener('keyup', e => {
if (e.which || e.keyCode === 13) {
if (document.queryCommandValue('formatBlock') === 'blockquote') {
exec('formatBlock', '<P>')
}
}
})

Detect if text is bold

I'm trying to make a WYSIWYG editor, and so far I have it so you can select text and click 'Make Bold' to make the selected text bold. It literally just wraps < b> (no space) tags around the selected text. But my problem is that if I want to un-bold that, my script has some trouble...
So far, here is my script:
<script language="javascript">
function format(tag) //defines function format
{
var editor = document.getElementById('editor');
var txt = '';
var tester = document.getElementById('tester');
if (window.getSelection) //if your browser uses this method of text selection
{
txt = window.getSelection();
}
else if (document.getSelection) //if your browser uses this method of text selection
{
txt = document.getSelection();
}
else if (document.selection) //if your browser uses this method of text selection
{
txt = document.selection.createRange().text;
}
else return; //Return this
matched = editor.innerHTML.match(txt); //Find the selected text in the editor
// if (matched.style.font-weight = "600") {tester.innerHTML = "already bold";} //if the selected text is bold, say 'already bold' DOES NOT WORK
// else {tester.innerHTML = "not bold";} //if it doesn't...
editor.innerHTML = editor.innerHTML.replace(matched,"<"+tag+">"+matched+"</"+tag+">");//Wrap <b> tags around it
}
</script>
<input type="button" value="Make Bold" onmousedown="format('b')">
<input type="button" value="Make Italic" onmousedown="format('i')">
<div id='editor' onclick="javascript:this.designMode='on';" designmode="on" contenteditable="true">Edit Box</div>
<span id="tester">testing span</span>
If you try it out you can type in that box and select text and click Make Bold and it will be bold. Now click Make Bold again but nothing happens. It's just adding another < b> tag around the selected text. I want it to make it un-bold; normal.
How do I do that?
Thanks :)
Messing with the HTML as a string is a bad idea. There are two better options: the first is to obtain the element containing the current user selection and use DOM methods and properties such as parentNode to test if it's bold. This is tricky to do cross-browser. Much easier is to use the execCommand method of document, which will automatically toggle boldness. It's supported in recent versions of all major browsers.
document.execCommand("bold", false, null);
UPDATE
Note that in Firefox (and possibly other browsers), this has no effect unless the document has designMode switched on. Here's a full example. Highlight some text and press Ctrl-B:
<html>
<head>
<title>Test</title>
<script type="text/javascript">
window.onload = function() {
document.designMode = "on";
};
function keyDown(evt) {
if (evt.keyCode == 66 && evt.ctrlKey) {
document.execCommand("bold", false, "");
}
return false;
}
</script>
</head>
<body onkeydown="return keyDown(event);">
<div>I like tea <b>with milk</b></div>
</body>
</html>

Keypress in jQuery: Press TAB inside TEXTAREA (when editing an existing text)

I want to insert TAB characters inside a TEXTAREA, like this:
<textarea>{KEYPRESS-INSERTS-TAB-HERE}Hello World</textarea>
I can insert before/after the existing TEXTAREA text - and I can insert / replace all text in the TEXTAREA - but have not yet been able to insert inside the existing TEXTAREA text (by the cursor) in a simple way.
$('textarea:input').live('keypress', function(e) {
if (e.keyCode == 9) {
e.preventDefault();
// Press TAB to append a string (keeps the original TEXTAREA text).
$(this).append("TAB TAB TAB AFTER TEXTAREA TEXT");
// Press TAB to append a string (keeps the original TEXTAREA text).
$(this).focus().prepend("TAB TAB TAB BEFORE TEXTAREA TEXT");
// Press TAB to replace a all text inside TEXTAREA.
$(this).val("INSERT INTO TEXTAREA / REPLACE EXISTING TEXT");
}
});
There is a "tabs in textarea" plug-in for jQuery ("Tabby") - but it's 254 code lines - I was hoping for just a few lines of code.
A few links that I studied: (again, I would prefer fewer code lines).
http://www.dynamicdrive.com/forums/showthread.php?t=34452
http://www.webdeveloper.com/forum/showthread.php?t=32317
http://pallieter.org/Projects/insertTab/
Please advise. Thanks.
I was creating a AJAX powered simple IDE for myself so I can rapidly test out PHP snippets.
I remember stumbling upon the same problem, here's how I solved it:
$('#input').keypress(function (e) {
if (e.keyCode == 9) {
var myValue = "\t";
var startPos = this.selectionStart;
var endPos = this.selectionEnd;
var scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos,this.value.length);
this.focus();
this.selectionStart = startPos + myValue.length;
this.selectionEnd = startPos + myValue.length;
this.scrollTop = scrollTop;
e.preventDefault();
}
});
#input is the ID of the textarea.
The code is not completely mine, I found it on Google somewhere.
I've only tested it on FF 3.5 and IE7. It does not work on IE7 sadly.
Unfortunately, manipulating the text inside textarea elements is not as simple as one might hope. The reason that Tabby is larger than those simple snippets is that it works better. It has better cross-browser compatibility and handles things like tabbing selections.
When minified, it's only about 5k. I'd suggest using it. You'll either have to discover and troubleshoot those same edge cases yourself anyway, or might not even know about them if users don't report them.
Yeah, dealing with input field selections across the different browsers is an annoyance, especially as in IE there are a few methods that look like they should work but actually don't. (Notably, combining using setEndPoint then measuring length, which looks OK until the selection starts or ends in newlines.)
Here's a couple of utility functions I use to deal with input selections. It returns the value of the input split into bits that are before, inside and after the selection (with the selection counting as an empty string at the input focus position if it's not a selection). This makes it fairly simply to replace and insert content at the point you want, whilst taking care of the IE CRLF problem.
(There may be a jQuery that does something like this, but I have yet to meet one.)
// getPartitionedValue: for an input/textarea, return the value text, split into
// an array of [before-selection, selection, after-selection] strings.
//
function getPartitionedValue(input) {
var value= input.value;
var start= input.value.length;
var end= start;
if (input.selectionStart!==undefined) {
start= input.selectionStart;
end= input.selectionEnd;
} else if (document.selection!==undefined) {
value= value.split('\r').join('');
start=end= value.length;
var range= document.selection.createRange();
if (range.parentElement()===input) {
var start= -range.moveStart('character', -10000000);
var end= -range.moveEnd('character', -10000000);
range.moveToElementText(input);
var error= -range.moveStart('character', -10000000);
start-= error;
end-= error;
}
}
return [
value.substring(0, start),
value.substring(start, end),
value.substring(end)
];
}
// setPartitionedValue: set the value text and selected region in an input/
// textarea.
//
function setPartitionedValue(input, value) {
var oldtop= input.scrollTop!==undefined? input.scrollTop : null;
input.value= value.join('');
input.focus();
var start= value[0].length;
var end= value[0].length+value[1].length;
if (input.selectionStart!==undefined) {
input.selectionStart= start;
input.selectionEnd= end;
if (oldtop!==null)
input.scrollTop= oldtop;
}
else if (document.selection!==undefined) {
var range= input.createTextRange();
range.collapse(true);
range.moveEnd('character', end);
range.moveStart('character', start);
range.select();
}
}
btw, see also:
http://aspalliance.com/346_Tabbing_in_the_TextArea

Categories

Resources