textbox defocuses after pressing tab key followed by any character in Firefox - javascript

I am trying to make an in-browser HTML editor, similar to CodePen and JSfiddle.I included a test to allow tabs without defocusing the editor. It works fine, except in Firefox. In Firefox, it keeps focus after pressing tab only to lose focus after the next keystroke.
let textbox = document.getElementById("preview-textbox");//textbox used for inserting HTML into iframe
textbox.value = "";
let iframe = document.querySelector("iframe");//used to render user's code
textbox.addEventListener("input", (e)=>{//inserts html from textbox into the iframe
iframe.src = "data:text/html," + encodeURI(textbox.value);
});
textbox.addEventListener("keydown", (e)=>{//allows indentation with 'tab'
let cursor_position = textbox.selectionStart;
let is_tab = e.keyCode || e.which;
if(is_tab === 9){
textbox.value = textbox.value.substr(0, cursor_position) + '\t' + textbox.value.substr(cursor_position, textbox.value.length);
let focus_textbox = setInterval(()=>{
textbox.focus();//refocuses textbox
textbox.selectionEnd = ++cursor_position;//sets cursor position
clearInterval(focus_textbox);}, 30);//clear setInterval
}
});

Related

How to select the previously "current active" element? Is there document.hadFocus?

How do I select the one of many input elements that had the cursor in it a split second before clicking a button to add something to the (previously) active input text box? Is there any method document.hadFocus? Can I get the id of the input using onFocusOut and pass it to my function?
I've seen many solutions in JQuery but can anyone do it in vanilla JS?
function insertAtCursor(newText, el = document.activeElement) {
//getElementsByTagName("input")[0].focus();
const start = el.selectionStart;
const end = el.selectionEnd;
const text = el.value;
const before = text.substring(0, start);
const after = text.substring(end, text.length);
el.value = (before + newText + after);
el.selectionStart = el.selectionEnd = start + newText.length;
el.focus();
}
I resolved this by replacing the onclick eventListener of my button (for adding text to an input box...)
with a focusout eventlistener on the previous element (the input box).
That way the event was tied to the input box and had everything I needed.
e.relatedTarget is the opposite of what I needed ("hadFocus"). It is "what element (if any) is getting the new focus of this focusout event?" The if statement uses this relatedTarget to make sure that the focus was lost to the button.
this is tied to the inputBox that "hadFocus" when the button was pressed.
inputBox.addEventListener( "focusout", insertAtCursor )
function insertAtCursor( event ){
if ( e.relatedTarget?.parentElement?.classList?.value == "buttonSet" ){
const text = this.value;
const start = this.selectionStart;
const end = this.selectionEnd;
const wordId = this.id;
const newTextToAddFromButton = e.relatedTarget.innerText;
...
}
}

IE10 - Inserting new line in <textarea> on keydown with javascript

I have a textbox where you type in your messages. Everytime the user presses ctrl + enter, a new line is created and the cursor should go to the next line. My code works on FF and Chrome. But in IE10, it behaves differently.
FF and Chrome behavior: When pressing ctrl + enter, the <textarea>'s value is stored inside a variable and then the <textarea> is applied with .focus().val('').val(prevMsgVal += "\r\n") which focuses on the <textarea> then clears its value and then placing a new value taken from the prevMsgVal variable (where the message before ctrl + enter was pressed is stored) is appended with "\r\n". - This works like the FB chat.
But in IE10, when you press ctrl + enter, it places a space or whitespace or something. And when you type in something, it goes to the new line!
Here's my current code:
if (evtobj.keyCode == 13 && evtobj.ctrlKey) {
$('#msgArea').focus().val('').val(prevMsgVal += "\r\n")
$('#msgArea').scrollTop = $('#msgArea').scrollHeight - $('#msgArea').clientHeight;
}
This only happens in IE10 but not in FF and Chrome. Did I append the new line the wrong way? Is there any other way to do this newline thing?
Not a direct solution to IE10's behavior, but I found a nifty fix to this problem here: David Walsh's Move Caret to end of TextArea
if (evtobj.keyCode == 13 && evtobj.ctrlKey) {
evtobj.preventDefault()
var tArea = document.getElementById("msgArea");
$('#msgArea').focus().val('').val(msgBoxVal += "\r\n")
moveCursorToEnd(tArea)
$('#msgArea').scrollTop = $('#msgArea').scrollHeight - $('#msgArea').clientHeight;
}
D. Walsh's function:
function moveCursorToEnd(el) {
if (typeof el.selectionStart == "number") {
el.selectionStart = el.selectionEnd = el.value.length;
} else if (typeof el.createTextRange != "undefined") {
el.focus();
var range = el.createTextRange();
range.collapse(false);
range.select();
}
}
It now moves the cursor/caret to the newline (which is the end of the textarea since I inserted it in val(msgBoxVal += "\r\n"))

How to set focus on child of content editable HTML element

I've been trying to create an advanced text input where users can write hashtags.
The input is a div with contenteditable set true, and the hashtags should be child nodes as I'd allow users to put space inside the hashtags.
My problem is that on some browsers I can not set the focus on the hashtag's child node as the user types. On Chrome/Linux and Safari/OSX it seems to work well, but on Firefox and Chrome/OSX setting the focus don't seem to work. (I haven't got to Windows yet.)
var $elComposer = $('#composer');
var InsertTagPair = function (tagtype) {
var newTag = document.createElement (tagtype);
$(newTag).attr ('contenteditable', 'true');
$(newTag).attr ('class', 'tag');
$elComposer.off ('keypress');
if (window.getSelection) {
var selection = window.getSelection();
if (selection.getRangeAt && selection.rangeCount) {
var range = selection.getRangeAt (0);
range.deleteContents ();
range.insertNode (newTag);
range.selectNodeContents (newTag);
range.collapse (false);
selection.removeAllRanges ();
selection.addRange (range);
};
};
newTag.focus ();
return newTag;
};
var ComposerOnKeyPressed = function (event) {
if (event.charCode == 35) { // #
var contextTag = InsertTagPair ('span');
$elComposer.attr ('contenteditable', 'false');
return false;
};
return event;
};
$elComposer.on ('keypress', ComposerOnKeyPressed);
The above code is the essential part that's not working. See it here in action:
JSFiddle - http://jsfiddle.net/cja963ym/1/
To see a more complete version of the composer that makes more sense see this instead:
JSFiddle - http://jsfiddle.net/g_borgulya/ur6zk32s/15/
Symptom: on Firefox if you type in the editable div and press '#', you manually have to click it by mouse or move the focus with tab to be able to edit the hashtag, while on other platforms it gets the focus when I call newTag.focus() on the element.
I don't know how to move on, even how to debug this problem.
Adding newTag.focus() in the "#" handler made it work in Chrome and Firefox (Win) (it didn't before, but did on IE11, just wanted to let you know)
Fiddle fork : http://jsfiddle.net/ekxo4ra3/
Does that look OK for what you wanted ?

asp.net textarea line feed and preventing postback on return key

I have an ASP.net web application with numerous pages.
Most of them have Multiline APS.net textbox and standard text box. Pressing the return key has unexpected result depending on browsers, page, last control used. It can fire any control either the master or the child page. Sometimes hitting the return key even fire the logout control.
So to prevent this I added:
body onkeydown="return (event.keyCode!=13)"
In the the master page body tag as recommended in many places, which works like a charm.
However, this cause the the return key not to respond to line feed in text area.
Users need to be able to insert line feed in Text area ( TextBoxMode.MultiLine)
How can I prevent this behavior?
You can use this
window.onload = function() {
setEvent("text", onKeyDown);
}
function onKeyDown()
{
return (event.keyCode!=13)
}
Which will cancel return button in only textboxes
Found a solution:
Keep:
body onkeydown="return (event.keyCode!=13)"
this will disable any post back using Return Key,
Then add to any multi line textbox the following attribute:
TextBox1.Attributes.Add("onkeyup", "EnterEvent(event,this)");
with the following javascript:
// add Line feed in text area.
function EnterEvent(e,ctl) {
var keycode = (e.keyCode ? e.keyCode : e.which);
if (keycode == 13) {
var st1 = $(ctl).textrange('get', 'start');
var l = ctl.value.length;
if (st1 < l) {
$(ctl).textrange('replace', '\n');
$(ctl).textrange('set', st1 + 1, 0);
}
else {
ctl.value = ctl.value + '\n';
}
}
}
this "manually" insert LF on return key up event.

Auto-scroll <textarea> with Javascript

I have this textarea that shows inputted text, but when the number of lines exceeds the size and width of the textarea, the user has to scroll down to see what they have last inputted.
I'd like the textarea to be set to the bottom everytime the enter button is pressed.
I've tried the following, but I can't get it to work:
function inputKeyDown(evt, input) {
if (evt.keyCode == 13) {
var textarea = document.getElementById("textarea");
textarea.value += "\n" + ">" + " " + input.value;
input.value = "";
return false;
}
var elem = document.getElementById('textarea');
elem.scrollTop = elem.scrollHeight;
}
and then I call the function keyDown in <input onKeyDown="return keyDown(event, this);" ...>
Any idea why no workie?
Try the following:
textarea.scrollTop = textarea.scrollHeight - textarea.clientHeight;
It depends on what sort of input you are looking at, but forcing the cursor back to the bottom could potentially be a serious usability problem. If you need a textarea that automatically expands, have a look at existing solutions such as this jQuery plugin
I'm not really sure if this is what you want but have a look this: http://jsfiddle.net/yV76p/
var textarea = document.getElementById("textarea");
textarea.onkeyup = function(evt) {
this.scrollTop = this.scrollHeight;
}

Categories