Mainly in Firefox, although it occasionally breaks in other browsers as well. If you check the jsfiddle below, especially if you go to the last tag and try to delete them all, you can't. Sometimes you can. It's not consistent.
<div id="testDiv" contentEditable="true">
Hey <input id="user-tag-1" class="ut ut-full-name" carpos="9" type="button" tabindex="-1" value="Rob"/>
</div>
I've seen this discussed on Mozilla's board as well as here, the workaround is generally to wrap the non contenteditable html in contenteditable <span>, <p>, <span>. Nothing I have seen actually fixes the problem for me. at least not completely. Even when I can delete the html, there's a lot of strange behavior.
Anyone know why this happens for contenteditable divs, and if it's just something that happens with non contenteditable html, is there a solution that would fix these issues, or do I have to write logic for the backspace and delete keys to check and delete the tags?
http://jsfiddle.net/mstefanko/qDkYq/
I answered this in detail here: https://stackoverflow.com/a/18069930/352335
As a summary, the way each browser handles contenteditable divs varies a lot. Digging through google plus's implementation of their posting widget is what gave me the inspiration I needed to fix this.
If you're going to render non-editable html elements inside a contenteditable:
For Chrome, use a <button> tag. And use the chrome only attribute contenteditable="plaintext-only" on the editable div. If you're appending html make sure to add a space with each element.
For firefox, use an <input> tag, and append a <br> element to the editable div. The <br> at the end of the div allows you to focus after elements, and fixed the issues I was having with deleting.
Related
In my app's tab loop, the <html> tag occupies a tab stop. I'm looking to remove the <html> tag from the tap loop.
I tried adding tabindex="-1" to the <html> tag, but on IE11 at least, that did not seem to remove the element from the tab loop. I'm close to spinning my own logic using JS to "skip" to the next focusable element if document.activeElement === <html>, but I'm wondering if there's an easier way.
The solution needs to be supported cross the major browsers: IE11, Edge, FF, Chrome, Safari.
Any ideas?
I visited HTML specification for tabindex attribute -> https://html.spec.whatwg.org/#the-tabindex-attribute
Below is the second para:
When the attribute is omitted, the user agent applies defaults. (There is no way to make an element that is being rendered be not focusable at all without disabling it or making it inert.)
As it is clearly mentioned that the only way to make any element not focusable is by making it disable or make it invisible from DOM.
I am still searching and will post an update on this.
Moreover, I also tried to replicate this issue and could not do it on IE.(did not try to replicate on other browser).
Update 1:
I found the difference in tabIndex between HTML4 AND HTML5:
It is stated that though HTML5 allows adding tabIndex attributes on any element, it may not have any effect. This is applicable to HTML element also. My I know, how do we know if an HTML element is focused?
Well according to my simple research i have found that you can use You can use tabindex="-1".
The W3C HTML5 specification supports negative tabindex values.
You can use also,which works for most browsers:
element.removeAttribute('tabindex');
I find this way with jquery but i'm not sure about
$('#yourelment').prop('tabIndex', -1);
Please check those link for more details :
How to ignore HTML element from tabindex?
Javascript/JQuery remove from tabindex
I have an editable div. The content of that div looks e.g. like that:
This is a <ins>new</ins> chapter.
(The tags are not visible, they are for styling)
If you set the text cursor in front of the "new" everything is fine. But if you set the text cursor behind the "new", the cursor is inside the < ins >-tag and new typed text is also inside the tag:
This is a <ins>new and very interesting</ins> chapter.
But it should look like that:
This is a <ins>new</ins> and very interesting chapter.
How can I set the text cursor behind the tag and prevent that new text is written inside the tag?
OK. The first idea was to made the
<ins contenteditable="false">new</ins>
Inside the contenteditable="true" element. Further reading (contenteditable=false inside contenteditable=true block is still editable in IE8) tells that this is not as always interpreted good in IE. In this post there is a hack answer (https://stackoverflow.com/a/7522910/1125465) but I really do not agree. It is just a mistake which will probably be repaired in the next versions of browsers.
Next I followed this link (HTML contenteditable with non-editable islands) and I haven;t got good news. There is no way of blocking the ins tag from editing so simple. First of all a little note:
If this isn't an additional functionality You must be sure it works as it should. As You wrote The user isn't allowed to write inside the -tag, so all the options:
working in almost every browser...
working with a little bug...
working but if someone...
must be rejected. So if someone turns the javascript off, it should work too. In that case I've come to the first conclusion (as always): server side verification MUST BE DONE.
This will prevent the user from destroying Your database and doing things he can't.
After server side verifying (and showing notification if something is wrong of course) it is going to be additional functionality. So we should do all we can now, to make it work (but now there is no obligation).
NICE LECTURE :)
https://stackoverflow.com/a/7232871/1125465
http://jsfiddle.net/X6Ab8/
**SOLUTION **
I propose something like... I know this sounds a little bit more like old days with milion tags, but really this will work and will be great.
Make an additional span element between the ins elements (for example using php:
$text = '<span contenteditable="true">'.$text.'</span>';
str_replace('<ins>', '</span><ins>', $text);
str_replace('</ins>', '</ins><span contenteditable="true">', $text);
Make this span editable, and only this span editable (not the block container). That's all. Solution is simple, clean, much more efficient and almost 100% safe. And nice...
ADDITIONAL SAFETY when using javascript hacks
If You need it to be done fully with javascript (maybe someone has idea how?), for total safety I would propose additionaly something like this:
Add data-noneditable-id="id" to each non editable element inside the main block editable container. Now every non editable element has it own unique id (can be done using jQuery for example using selector $("div#editable ins")).
Run a javascript that will run through all the objects that has attribute "data-noneditable-id" and save their innerHTML in array (for example: 1 => 'new', 2=> 'added', 3=> 'inserted', ...).
Now if someone edit any of them, You can easily repair them.
PS. This should also help a little... (https://stackoverflow.com/a/4979828/1125465).
Hope it helps! Best regards.
There are so many issues with contenteditable divs and deleting html and/or non content editable content inside editable divs.
Using an answer by the excellent Tim Down here: How to delete an HTML element inside a div with attribute contentEditable?
Using Tim's code, the entire text node gets deleted. I need this to work like any textarea would, deleting character by character and just making sure html elements can be backspaced as well.
I tried the following
else if(node){
var index = node.length-1;
if(index >= 0)
node.deleteData(index,1);
else
this.removeChild(node);
}
But this is obviously not going to work correctly. If I am at the end of the content, things work as expected. But if I place the cursor anywhere else, it's still deleting from the end.
I'm lost at this point, any help is very appreciated
http://jsfiddle.net/mstefanko/DvhGd/1/
After breaking down how google uses contenteditable divs in their google plus user tagging, I landed on a much more reasonable solution. Maybe it will help someone else out.
After adding 1 tag, you can already see a lot of differences in the html browser to browser.
In Google Chrome, a space is added with each tag. The button tag is used. And the chrome-only contenteditable="plaintext-only" is used.
When I backspace the space in chrome, a BR tag is then appended.
In Firefox the BR tag is added immediately with the first tag. No spaces are needed. And an input tag is used instead of the button tag.
The BR tag was the single greatest break-through I had while digging through this. Before adding this, there was a lot of quirky behavior with deleting tags, as well as focus issues.
In IE, more interesting changes were made. A span with contenteditable false is used for the tags here. No spaces or BR tags, but an empty text node.
With all of that, you don't have to copy google exactly.
The important parts:
If you're rendering HTML, do the following...
1. Chrome should use the button tag
2. Firefox/IE should use the input tag
For range/selection you generally want to treat things like tags as a single character. You can build this into your range/selection logic, but the behavior of the input/button tags is much more consistent, and way less code.
IE behaves better in IE7-8 using a span. Just from a UI standpoint. But if you don't care if your site is pretty in old versions of IE, the input has the correct behaviour in IE as well as firefox.
3. Chrome only, use the contenteditable="plaintext-only" attribute on your editable div.
Otherwise, a lot of weird issues happen not only when a user tries to paste rich-text, but also when deleting html elements sometimes the styles can get transferred to the div, I noted many strange issues with this.
4. If you need to set the caret position to the end of the div, set the end of the range before the BR.
for FireFox:
range.setEndBefore($(el).find('br')[0]);
I've been tinkering with this a little bit as well and can't quite understand why the styles get applied to the search text box but not the dropdown like it does on the template. Any ideas on why this could be happening.
http://jsfiddle.net/NNk7s/2/
Template: http://kansasoutlawwrestling.com/peach/tables.html
I can see what's happening, although I don't know enough about this plugin to tell you why. There are two "dropdown menus" in the working example. One is a real HTML <select> tag with <option> tags, but this form element is hidden with a style="display: none" attribute.
What you're seeing on the page is actually a fancy, styled <div> tag designed to look like a dropdown menu. The <select> tag is likely only there for compatibility with older browsers, or maybe if the user has JavaScript disabled.
You'll need to figure out what you need to do to get the plugin to create that fake dropdown overlay for you. It's probably just a matter of creating a <div> or some other element and applying a CSS class to it.
I'am currently developing a WYSIWYG editor for my CMS and got serious bugs here. After switching from IFRAME to DIV contenteditable the behavior changed dramatically.
Using execCommand('formatBlock') to create headlines causes unwanted BR tags to the source code, but only in Mozilla. I thought the reason could be <br _moz_dirty=""> but I could be wrong and did not find a way to fix it.
See demo here: http://jsfiddle.net/Kj9Rp/
Definitely a bug. I've noticed that the relatively recently added contenteditable functionality in Mozilla has a number of quirks not present with designMode. I would stick with the <iframe> and designMode for now and file a bug at Mozilla's Bugzilla.
Your other option is to write your own DOM manipulation code that surrounds selected text within an <h1> element, but that will be relatively involved to get absolutely right.