When using contentEditable in Firefox, is there a way to prevent the user from inserting paragraph or line breaks by pressing enter or shift+enter?
You can attach an event handler to the keydown or keypress event for the contentEditable field and cancel the event if the keycode identifies itself as enter (or shift+enter).
This will disable enter/shift+enter completely when focus is in the contentEditable field.
If using jQuery, something like:
$("#idContentEditable").keypress(function(e){ return e.which != 13; });
...which will return false and cancel the keypress event on enter.
This is possible with Vanilla JS, with the same effort:
document.getElementById('idContentEditable').addEventListener('keypress', (evt) => {
if (evt.which === 13) {
evt.preventDefault();
}
});
You should not use jQuery for the most simple things. Also, you may want to use "key" instead of "which": https://developer.mozilla.org/en-US/docs/Web/Events/keypress
Update, since keypress is deprecated:
document.getElementById('idContentEditable').addEventListener('keydown', (evt) => {
if (evt.keyCode === 13) {
evt.preventDefault();
}
});
Add the following CSS rule to hide line breaks. This is only a style setting, you should add some event handlers to prevent inserting line breaks:
.your_editable br {
display: none
}
Other than adding line breaks, the browser adds additional tags and styles (when you paste text, the browser also appends your pasted text style).
The code below covers it all.
When you press enter, no line breaks will be added.
When you paste text, all elements added by the browser are stripped from the text.
$('[contenteditable]').on('paste', function(e) {
//strips elements added to the editable tag when pasting
var $self = $(this);
setTimeout(function() {$self.html($self.text());}, 0);
}).on('keypress', function(e) {
//ignores enter key
return e.which != 13;
});
Click here for a live example
another option is to allow breaks to be entered but remove them on blur. this has the advantage of dealing with pasted content. your users will either love it or hate it (depending on your users).
function handle_blur(evt){
var elt=evt.target; elt.innerText=elt.innerText.replace(/\n/g,' ');
}
then, in html:
<span onblur="handle_blur(event)" contenteditable>editable text</span>
If you are using JQuery framework, you can set it with the on method which will let you have the desired behavior on all elements even if this one is added lately.
$(document).on('keypress', '.YourClass', function(e){
return e.which != 13;
});
Add:
display: flex;
On the contenteditable html element
$("#idContentEditable").keypress(function(e){ return e.which != 13; });
Solution proposed by Kamens doesn't work in Opera, you should attach event to document instead.
/**
* Pass false to enable
*/
var disableEnterKey = function(){
var disabled = false;
// Keypress event doesn't get fired when assigned to element in Opera
$(document).keypress(function(e){
if (disabled) return e.which != 13;
});
return function(flag){
disabled = (flag !== undefined) ? flag : true;
}
}();
If you want to target all the contentEditable fields use
$('[contenteditable]').keypress(function(e){ return e.which != 13; });
I came here searching for the same answer, and was surprised to find it's a rather simple solution, using the tried and true Event.preventDefault()
const input = document.getElementById('input');
input.addEventListener('keypress', (e) => {
if (e.which === 13) e.preventDefault();
});
<div contenteditable="true" id="input">
You can edit me, just click on me and start typing.
However, you can't add any line breaks by pressing enter.
</div>
Use CSS:
word-break: break-all;
For me, its worked!
Related
I'm trying to let the user check/uncheck the checkbox on hitting either spacebar or enter in keyboard, I want to achieve this functionality using JavaScript function.
This is how my code looks partially:
<span class="sample" onClick="UdateComponent" tabindex="0" role="checkbox" aria-checked="" aria-decribedby="">
Inside this span I want to include onkeypress or onkeydown for achieving the functionality that is mentioned above and the constraint is I only have to use JavaScript for this.
I would strongly recommend not doing this. Use an input type="checkbox", in combination with a label. It's what they're for. You can style them extremely thoroughly. You can even hide the input type="checkbox" if you want to and only show the label.
But you've said you can't use input. So yes, you can do this with a keypress handler. You'll presumably also want to handle clicks. See comments:
// Handle toggline the "checkbox"
// Expects the element as `this` and the event as `e`
function toggleFakeCheckbox(e) {
// States as far as I can tell from
// https://www.w3.org/TR/wai-aria/states_and_properties#aria-checked
// and
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_checkbox_role
this.setAttribute(
"aria-checked",
this.getAttribute("aria-checked") === "true" ? "false" : "true"
);
// Avoid the default (spacebar in particular is problematic)
e.preventDefault();
e.stopPropagation();
}
// Get the element
var sample = document.querySelector(".sample");
// Set up its handlers for click and keypress
sample.addEventListener("click", toggleFakeCheckbox);
sample.addEventListener("keypress", function(e) {
// Flag for whether to toggle
var toggle = false;
var keyCode;
if ("key" in e) {
// Modern user agent
toggle = e.key === " " || e.key === "Enter";
} else {
// Fallback for older user agents
keyCode = e.which || e.keyCode;
toggle = keyCode === 32 || keyCode === 13;
}
if (toggle) {
toggleFakeCheckbox.call(this, e);
}
});
// Give it focus for easy testing
sample.focus();
/* Let's show the state of the checkbox */
[role=checkbox][aria-checked=true]:before {
content: '[x] '
}
[role=checkbox][aria-checked=false]:before {
content: '[ ] '
}
<span class="sample" tabindex="0" role="checkbox" aria-checked="true" aria-decribedby="">Checkbox</span>
But again: Reinventing the wheel isn't a good thing, even if you try to respect all the ARIA rules when doing so...
Update: And sure enough, focussing the span in IE and hitting the space bar moves us to a different part of the page, even though we both prevented the default action (which was enough to stop that on Firefox) and stopped propagation. Why does it do that? Because we tried to reinvent the wheel. Which is a Bad Thing™.
We've been busy with upgrading TinyMCE from 3.x to 4.2.5 and can not prevent the default ENTER action from happening.
Our goal is to submit the form when CTRL + enter is pressed, and important is that the submit should happen before the newline is added to TinyMCE. The 3.x branch allowed us to add the event to the top of the queue:
// Important: inject new eventHandler via addToTop to prevent other events
tinymce.get('tinymce_instance').onKeyDown.addToTop(function(editor, event) {
if (event.ctrlKey && event.keyCode == 13) {
$("form").submit();
return false;
}
});
Unfortunately we can not figure out how to add it to the top of the events again.
event.preventDefault() and event.stopPropagation() do not have the expected effect because the enter is already there. The weird thing is that it does work on other keys, the alphanumeric keys can be prevented. http://jsfiddle.net/zgdcg0cj/
The event can be added using the following snippet:
tinymce.get('tinymce_instance').on('keydown', function(event) {
if (event.ctrlKey && event.keyCode == 13) {
$("form").submit();
return false;
}
});
Problem: the newline is added to the TinyMCE content earlier as our event handler is called, so an unwanted enter is stored. How can I add the event to the top in the 4.x branch, or prevent the newline from happening?
event.preventDefault() works when you attach the keydown event via the setup on the init function.
tinymce.init({
selector:'textarea',
setup: function (ed) {
ed.on('keydown',function(e) {
if(e.ctrlKey && e.keyCode == 13){
alert("CTRL + ENTER PRESSED");
e.preventDefault();
}
});
}
});
This does block the carriage return from happening. JsFiddle
Edit:
Above is one way of doing it, I have found another way of achieving the result which doesn't require the init at all. Instead we create a new Editor instance and bind to our textarea given it has an id.
HTML
<form>
<!--Select by ID this time -->
<textarea id='editor_instance_1'>A different way</textarea>
</form>
JS
var ed = new tinymce.Editor('editor_instance_1', {
settings: "blah blah"
}, tinymce.EditorManager);
//attach keydown event to the editor
ed.on('keydown', function(e){
if(e.ctrlKey && e.keyCode == 13){
alert("CTRL + ENTER");
e.preventDefault();
}
});
//render the editor on screen
ed.render();
var init {
...,
setup: function (ed) {
ed.on('keydown', function (e) {
if (e.ctrlKey && 13 === e.keyCode) {
e.preventDefault();
$("form").submit();
}
});
};
tinymce.init(init);
Works for tinyMCE 4.x
Maybe I'm late, but this answer is for those who cannot(or don't want to) change init setup for tinymce. I found following method:
var frame = document.getElementById('id_of_editor_iframe');
var iframeDocument = fr.contentWindow.document;
iframeDocument.addEventListener('keydown', function(e) {
if (
[38, 40, 13].indexOf(e.keyCode) > -1 //Enter and up/down arrows or whatever you want
) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
// your code here
return false;
}
}, true);
It helped me to prevent new line in editor
I am trying to disable spaces in the Username text field, however my code disables using the back arrow too. Any way to allow the back arrow also?
$(function() {
var txt = $("input#UserName");
var func = function() {
txt.val(txt.val().replace(/\s/g, ''));
}
txt.keyup(func).blur(func);
});
fiddle: http://jsfiddle.net/EJFbt/
You may add keydown handler and prevent default action for space key (i.e. 32):
$("input#UserName").on({
keydown: function(e) {
if (e.which === 32)
return false;
},
change: function() {
this.value = this.value.replace(/\s/g, "");
}
});
DEMO: http://jsfiddle.net/EJFbt/1/
This seems to work for me:
<input type="text" onkeypress="return event.charCode != 32">
It doesn't "disable" the back arrow — your code keeps replacing all the text outright, whenever you press a key, and every time that happens the caret position is lost.
Simply don't do that.
Use a better mechanism for banning spaces, such as returning false from an onkeydown handler when the key pressed is space:
$(function() {
$("input#Username").on("keydown", function (e) {
return e.which !== 32;
});
});
This way, your textbox is prohibited from receiving the spaces in the first place and you don't need to replace any text. The caret will thus remain unaffected.
Update
#VisioN's adapted code will also add this space-banning support to copy-paste operations, whilst still avoiding text-replacement-on-keyup handlers that affect your textbox value whilst your caret is still active within it.
So here's the final code:
$(function() {
// "Ban" spaces in username field
$("input#Username").on({
// When a new character was typed in
keydown: function(e) {
// 32 - ASCII for Space;
// `return false` cancels the keypress
if (e.which === 32)
return false;
},
// When spaces managed to "sneak in" via copy/paste
change: function() {
// Regex-remove all spaces in the final value
this.value = this.value.replace(/\s/g, "");
}
// Notice: value replacement only in events
// that already involve the textbox losing
// losing focus, else caret position gets
// mangled.
});
});
Try checking for the proper key code in your function:
$(function(){
var txt = $("input#UserName");
var func = function(e) {
if(e.keyCode === 32){
txt.val(txt.val().replace(/\s/g, ''));
}
}
txt.keyup(func).blur(func);
});
That way only the keyCode of 32 (a space) calls the replace function. This will allow the other keypress events to get through. Depending on comparability in IE, you may need to check whether e exists, use e.which, or perhaps use the global window.event object. There are many question on here that cover such topics though.
If you're unsure about a certain keyCode try this helpful site.
One liner:
onkeypress="return event.which != 32"
I just wrote this nifty little function which works on the form itself...
$("#form").keypress(function(e) {
if (e.which == 13) {
var tagName = e.target.tagName.toLowerCase();
if (tagName !== "textarea") {
return false;
}
}
});
In my logic I want to accept carriage returns during the input of a textarea. Also, it would be an added bonus to replace the enter key behavior of input fields with behavior to tab to the next input field (as if the tab key was pressed). Does anyone know of a way to use the event propagation model to correctly fire the enter key on the appropriate element, but prevent form submitting on its press?
You can mimic the tab key press instead of enter on the inputs like this:
//Press Enter in INPUT moves cursor to next INPUT
$('#form').find('.input').keypress(function(e){
if ( e.which == 13 ) // Enter key = keycode 13
{
$(this).next().focus(); //Use whatever selector necessary to focus the 'next' input
return false;
}
});
You will obviously need to figure out what selector(s) are necessary to focus on the next input when Enter is pressed.
Note that single input forms always get submitted when the enter key is pressed. The only way to prevent this from happening is this:
<form action="/search.php" method="get">
<input type="text" name="keyword" />
<input type="text" style="display: none;" />
</form>
Here is a modified version of my function. It does the following:
Prevents the enter key from working
on any element of the form other
than the textarea, button, submit.
The enter key now acts like a tab.
preventDefault(), stopPropagation() being invoked on the element is fine, but invoked on the form seems to stop the event from ever getting to the element.
So my workaround is to check the element type, if the type is not a textarea (enters permitted), or button/submit (enter = click) then we just tab to the next thing.
Invoking .next() on the element is not useful because the other elements might not be simple siblings, however since DOM pretty much garantees order when selecting so all is well.
function preventEnterSubmit(e) {
if (e.which == 13) {
var $targ = $(e.target);
if (!$targ.is("textarea") && !$targ.is(":button,:submit")) {
var focusNext = false;
$(this).find(":input:visible:not([disabled],[readonly]), a").each(function(){
if (this === e.target) {
focusNext = true;
}
else if (focusNext){
$(this).focus();
return false;
}
});
return false;
}
}
}
From a usability point of view, changing the enter behaviour to mimic a tab is a very bad idea. Users are used to using the enter key to submit a form. That's how the internet works. You should not break this.
The post Enter Key as the Default Button describes how to set the default behaviour for enter key press. However, sometimes, you need to disable form submission on Enter Key press. If you want to prevent it completely, you need to use OnKeyPress handler on tag of your page.
<body OnKeyPress="return disableKeyPress(event)">
The javascript code should be:
<script language="JavaScript">
function disableEnterKey(e)
{
var key;
if(window.event)
key = window.event.keyCode; //IE
else
key = e.which; //firefox
return (key != 13);
}
</script>
If you want to disable form submission when enter key is pressed in an input field, you must use the function above on the OnKeyPress handler of the input field as follows:
<input type="text" name="txtInput" onKeyPress="return disableEnterKey(event)">
Source: http://www.bloggingdeveloper.com/post/Disable-Form-Submit-on-Enter-Key-Press.aspx
Set trigger for both the form and the inputs, but when the input events are triggered, stop the propagation to the form by calling the stopPropagation method.
By the way, IMHO, it's not a great thing to change default behaviors to anything any average user is used to - that's what make them angry when using your system. But if you insist, then the stopPropagation method is the way to go.
In my case i wanted to prevent it only in a dinamically created field, and activate some other button, so it was a little bit diferent.
$(document).on( 'keypress', '.input_class', function (e) {
if (e.charCode==13) {
$(this).parent('.container').children('.button_class').trigger('click');
return false;
}
});
In this case it will catch the enter key on all input's with that class, and will trigger the button next to them, and also prevent the primary form to be submited.
Note that the input and the button have to be in the same container.
The previous solutions weren't working for me, but I did find a solution.
This waits for any keypress, test which match 13, and returns false if so.
in the <HEAD>
function stopRKey(evt) {
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
if ((evt.which == 13) && (node.type == "text")) {
return false;
}
}
document.onkeypress = stopRKey;
I prefer the solution of #Dmitriy Likhten, yet:
it only worked when I changed the code a bit:
[...] else
{
if (focusNext){
$(this).focus();
return false; } //
}
Otherwise the script didn't work.
Using Firefox 48.0.2
I modified Dmitriy Likhten's answer a bit, works good. Included how to reference the function to the event. note that you don't include () or it will execute. We're just passing a reference.
$(document).ready(function () {
$("#item-form").keypress(preventEnterSubmit);
});
function preventEnterSubmit(e) {
if (e.which == 13) {
var $targ = $(e.target);
if (!$targ.is("textarea") && !$targ.is(":button,:submit")) {
var focusNext = false;
$(this).find(":input:visible:not([disabled],[readonly]), a").each(function () {
if (this === e.target) {
focusNext = true;
} else {
if (focusNext) {
$(this).focus();
return false;
}
}
});
return false;
}
}
}
I’m working with basic HTML <input type="text"/> text field with a numeric value.
I’m adding JavaScript event keyup to see when user presses arrow up key (e.which == 38) – then I increment the numeric value.
The code works well, but there’s one thing that bugs me. Both Safari/Mac and Firefox/Mac move cursor at the very beginning when I’m pressing the arrow up key. This is a default behavior for every <input type="text"/> text field as far as I know and it makes sense.
But this creates not a very aesthetic effect of cursor jumping back and forward (after value was altered).
The jump at the beginning happens on keydown but even with this knowledge I’m not able to prevent it from occuring. I tried the following:
input.addEventListener('keydown', function(e) {
e.preventDefault();
}, false);
Putting e.preventDefault() in keyup event doesn’t help either.
Is there any way to prevent cursor from moving?
To preserve cursor position, backup input.selectionStart before changing value.
The problem is that WebKit reacts to keydown and Opera prefers keypress, so there's kludge: both are handled and throttled.
var ignoreKey = false;
var handler = function(e)
{
if (ignoreKey)
{
e.preventDefault();
return;
}
if (e.keyCode == 38 || e.keyCode == 40)
{
var pos = this.selectionStart;
this.value = (e.keyCode == 38?1:-1)+parseInt(this.value,10);
this.selectionStart = pos; this.selectionEnd = pos;
ignoreKey = true; setTimeout(function(){ignoreKey=false},1);
e.preventDefault();
}
};
input.addEventListener('keydown',handler,false);
input.addEventListener('keypress',handler,false);
I found that a better solution is just to return false; to prevent the default arrow key behavior:
input.addEventListener("keydown", function(e) {
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') return false;
}, false);
Actually, there is a better and simpler method to do this job.
$('input').bind('keydown', function(e){
if(e.keyCode == '38' || e.keyCode == '40'){
e.preventDefault();
}
});
Yes, it is so easy!
In my case (react) helped:
onKeyDown = {
(e) => {
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') e.preventDefault();
}
}
and onKeyUp was fully functional
I tested the code and it seems that it cancels the event but if you don't press the arrow for very short time - it fires keypress event and that event actually moves cursor. Just use preventDefault() also in keypress event handler and it should be fine.
Probably not. You should instead seek for a solution to move the cursor back to the end of the field where it was. The effect would be the same for the user since it is too quick to be perceived by a human.
I googled some and found this piece of code. I can't test it now and it is said to not to work on IE 6.
textBox.setSelectionRange(textBox.value.length, textBox.value.length);