Contenteditable paragraph tag on enter - html

I was wondering if there is an acceptable way to force all major browsers to insert paragraph tag instead of the default tag that they insert on pressing enter key when contentEditable is true.
As far as I know IE inserts p automatically. But Google Chrome inserts div tag and Firefox inserts br (WTF?!).
Thanks in advance!

you can use document.execCommand('formatBlock', false, 'p'); in event like keypress or keydown, etc. to use paragraphs after enter press. For example:
element.addEventListener('keypress', function(ev){
if(ev.keyCode == '13')
document.execCommand('formatBlock', false, 'p');
}, false);

As its build in the browser you can't change that behaviour. You could work around by detecting browser and replacing elements correspondingly. Very ugly, I know.
Also check WhatWG for background: http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2011-May/031577.html

I had this same problem and found the solution (CHROME, MSIE, FIREFOX), follow my code in the link.
$(document).on('click','#myButton',function() {
if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1)
var str = $('#myDiv').html().replace(/<br>/gi,'').replace(/<div>/gi,'<br>').replace(/<\/div>/gi,'');
else if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1)
var str = $('#myDiv').html().replace(/<\/br>/gi,'').replace(/<br>/gi,'<br>').replace(/<\/br>/gi,'');
else if (navigator.userAgent.toLowerCase().indexOf("msie") == -1)
var str = $('#myDiv').html().replace(/<br>/gi,'').replace(/<p>/gi,'<br>').replace(/<\/p>/gi,'');
$('#myDiv2').removeClass('invisible').addClass('visible').text(str);
$('#myDiv3').removeClass('invisible').addClass('visible').html(str);
});
https://jsfiddle.net/kzkxo70L/1/

Related

How to prevent HTML audio controls from getting focus during TAB key navigation?

I have an HTML page with a bunch of HTML audio elements (with enabled controls) interwined with text input elements. Audio elements have tabindex="-1", and text inputs have positive tabindex. This does not prevent Chrome from iterating over 6 control elements when doing TAB key navigation.
Maybe audio controls are exempt from tabindex behavior: https://github.com/w3c/webcomponents/issues/762 but if not:
Can one disallow them from getting focus from keyboard (without JavaScript; my JS workaround is below)? I'd like the user to be able to use TAB to iterate only text inputs (and use mouse to play audio if necessary), it's for a crowdsourcing scenario, so saving user effort is important.
Following #makusium's comment I came up with the following JavaScript workaround:
function onkeydown_(evt)
{
const tab = evt.keyCode == 9, shift = evt.shiftKey;
const tabIndex = (document.activeElement || {tabIndex : -1}).tabIndex;
if(tab)
{
const newTabIndex = shift ? Math.max(0, tabIndex - 1) : tabIndex + 1;
const newElem = document.querySelector(`[tabindex="${newTabIndex}"`);
if(newElem)
newElem.focus();
return false;
}
return true;
}
document.addEventListener('keydown', onkeydown_);

Copying text with a new line to <input type="text"/> not working in IE

My problem is the following:
I have an input, simple as that:
<input type="text"/>
And when I try to paste some text that contains a new line in it, all the text after the new line does not appear.
Now I know this type of input shouldn't support such behavior, and the best scenario is to use a textarea but that would be hardly achievable in the current project I am working on.
However, other browsers convert the new line to a space character and append the text after the new line so you eventually get the whole text in a single line. IE doesn't do that.
I have found the following solution to intercept paste event and I thought maybe I can use it to transform the string into a single-lined but it doesn't work in firefox. I can try a browser detection but I am afraid it can fail in many other scenarios as well.
Is there something else that I can do to make IE behave like other browsers and what are my best options?
I found this answer that might be the solution to your problem:
JavaScript get clipboard data on paste event (Cross browser)
It should work in IE6+, FF 22+, Chrome & Safari.
HTML
<input id='editableDiv' contenteditable='true' type="text"/>
JavaScript
function handlePaste (e) {
var clipboardData, pastedData;
// Stop data actually being pasted into input field
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Remove new line characters
alert(pastedData);
var res = pastedData.replace(/\r?\n|\r/g, );
}
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
Hope this helps mate.
Thanks for your answer George K - yours was the base for my solution. I had a few remaining problems to get past:
addEventListener was giving me 'element not found'
concatenated value wasn't populating the field
So I ended up with these slight modifications to your javascript:
function handlePaste(e) {
var clipboardData, pastedData;
// Stop data actually being pasted into input field
e.stopPropagation();
e.preventDefault();
// Get pasted data via clipboard API
clipboardData = e.clipboardData || window.clipboardData;
pastedData = clipboardData.getData('Text');
// Remove new line characters
var res = pastedData.replace(/\r?\n|\r/g, ' ');
document.getElementById(e.target.id).value = res; // <- added this to populate value
}
// added this also - this fixed my 'element not found' error
window.addEventListener('load', function () {
document.getElementById('editableDiv').addEventListener('paste', handlePaste);
})
BTW, I am using an <asp:textbox> instead of an <input> element.
This works for me in both IE (11) and Chrome (83.x).

How to make HTML5 contenteditable div allowing only text in firefox?

I want to make div with contentEditable attribute which is allowing only text. It's easily achievable in Chrome by using:
<div contenteditable="plaintext-only"></div>
However it doesn't work in Firefox. Is there a way how to make text-only contenteditable div in Firefox ? I know it is possible, because Google Plus has such div, but I don't know how they do it.
I ran into this problem myself. Here is my solution which I have tested in Firefox and Chrome:
Ensure the contenteditable div has the css white-space: pre, pre-line or pre-wrap so that it displays \n as new lines.
Override the "enter" key so that when we are typing, it does not create any <div> or <br> tags
myDiv.addEventListener("keydown", e => {
//override pressing enter in contenteditable
if (e.keyCode == 13)
{
//don't automatically put in divs
e.preventDefault();
e.stopPropagation();
//insert newline
insertTextAtSelection(myDiv, "\n");
}
});
Secondly, override the paste event to only ever fetch the plaintext
//override paste
myDiv.addEventListener("paste", e => {
//cancel paste
e.preventDefault();
//get plaintext from clipboard
let text = (e.originalEvent || e).clipboardData.getData('text/plain');
//insert text manually
insertTextAtSelection(myDiv, text);
});
And here is the supporting function which inserts text into the textContent of a div, and returns the cursor to the proper position afterwards.
function insertTextAtSelection(div, txt) {
//get selection area so we can position insert
let sel = window.getSelection();
let text = div.textContent;
let before = Math.min(sel.focusOffset, sel.anchorOffset);
let after = Math.max(sel.focusOffset, sel.anchorOffset);
//ensure string ends with \n so it displays properly
let afterStr = text.substring(after);
if (afterStr == "") afterStr = "\n";
//insert content
div.textContent = text.substring(0, before) + txt + afterStr;
//restore cursor at correct position
sel.removeAllRanges();
let range = document.createRange();
//childNodes[0] should be all the text
range.setStart(div.childNodes[0], before + txt.length);
range.setEnd(div.childNodes[0], before + txt.length);
sel.addRange(range);
}
https://jsfiddle.net/1te5hwv0/
Sadly, you can’t. As this answer points out the spec only specifies true, false and inherit as valid parameters. The subject seems to have been discussed but if I’m not mistaken only Webkit implements support for plaintext-only.

html anchor works only once

I am ashamed to say that I have an anchor issue.
So I have this code:
<a name="map"></a>
$("div.store_list").click(function() {
//do some stuff
location.href = location.href + '#map'
});
When doing the first click it works fine. And the URL changes to:
http://mydomain.local/stores#map
Second click the URL changes to the following and it doesn't work:
http://mydomain.local/stores#map#map
Any suggestions? Thanks
In case you scroll and need to jump again, this has worked for me:
onclick="location.hash=''; location.hash='#map';"
Try location.hash instead, e.g.
location.hash='#map'
Issue was solved using: document.location = "#map";
You can check to make sure the URL doesn't already contain the value you're appending:
$("div.store_list").click(function() {
//do some stuff
if (location.href.indexOf('#map') == -1) {
location.href += '#map';
}
});
The accepted solution didn't work for me sadly. I managed to get it to work in Chrome by setting the anchor value to "#" first, then setting it to my desired location.
document.location.href = "#";
document.location.href = "#myAnchor";
Once I did this, it fired every time I click a link with an anchor tag in it.
$(document).on('click', '.jump_to_instance', e => {
// Get anchor name
var anchorName = $(e.target).attr("href");
// Set anchor to nothing first
document.location.href = "#";
// Set to new anchor value
document.location.href = anchorName;
});
Click me to go to anchor, I should work multiple times
<div id="myAnchor">Will jump to here</div>
Reseting the scroll position on anchor link click event worked for me.
Seems like theres at least one bug with anchor links in Chrome versions 76 - 86 (The most recent macOS version at time of this posting).
Try:
window.scrollTo(0, 0)

problems with execCommand justification in Firefox?

I am building a very simple WYSWIG editor for a div with contenteditable = "true". I am using execCommand to do simple formatting such as bold, italicize, and underline along with text justification.
PROBLEM: Bold, italic, underline all work but using justifyCenter (or any justify) doesn't work in Firefox but works in Chrome and Safari. Chrome and Safari don't seem to like my justifyRight but works just fine with justifyLeft and justifyCenter. In Firefox I get the following:
uncaught exception: [Exception... "Component returned failure code:
0x80004005 (NS_ERROR_FAILURE) [nsIDOMNSHTMLDocument.execCommand]"
nsresult: "0x80004005 (NS_ERROR_FAILURE)"
I can't figure out what is wrong but wonder it if might have something to do with designMode needing to be set to on in Firefox? However, bold, italic, and underline are working just fine without me explicitly turning on designMode.
Any ideas? Thanks in advance.
I know it's sort of a late answer, and you probably figured it out already, but for anyone who hasn't, try setting contenteditable to true for the body. I'm trying to find a way around this because every browser justifies the text just fine without it on, and I don't want the whole page editable.
The bug is referenced here : https://bugzilla.mozilla.org/show_bug.cgi?id=442186
Someone proposed this workaround :
try
{
document.execCommand('justifyright', false, null);
}
catch (e)
{
//special case for Mozilla Bug #442186
if(e && e.result == 2147500037)
{
//probably firefox bug 442186 - workaround
var range = window.getSelection().getRangeAt(0);
var dummy = document.createElement('br');
//find node with contentEditable
var ceNode = range.startContainer.parentNode;
while(ceNode && ceNode.contentEditable != 'true')
ceNode = ceNode.parentNode;
if(!ceNode)
throw 'Selected node is not editable!';
ceNode.insertBefore(dummy, ceNode.childNodes[0]);
document.execCommand('justifyright', false, null);
dummy.parentNode.removeChild(dummy);
}
else if(console && console.log)
console.log(e);
}
It consists in creating a dummy element (a <br />) and remove it after the execution of the justify* command.