Contenteditable=False Inside Contenteditable=True Block Is Still Editable in IE8

contenteditable=false inside contenteditable=true block is still editable in IE8

Okay, I already have discovered the answer much like how Penicillin was discovered.

You see, playing around with this code, I mistakenly set contenteditable to true for the span and voila! It worked!

So, to make a span NON-contenteditable inside a contenteditable div, you just set its contenteditable attribute to true!

<div contenteditable="true">
Luke, I am your father.
<span contenteditable="true">I'm your son?! Ewww!</span>
Don't speak back to me!
</div>

Here's the file to demonstrate (use IE8 to open it): https://codepen.io/hgezim/pen/qMppLg .

Lastly, I didn't post the question to get votes (although, they wouldn't hurt!), but since the solution was so ridiculous and I didn't find it here, I thought someone may find this tip time saving.

HTML5 - contenteditable= false nested in contenteditable= true

This is a bug in Internet Explorer 11. Section 7.6.1 of the HTML5 specification states:

The contenteditable attribute is an enumerated attribute whose keywords are the empty string, true, and false. The empty string and the true keyword map to the true state. The false keyword maps to the false state. In addition, there is a third state, the inherit state, which is the missing value default (and the invalid value default).

The true state indicates that the element is editable. The inherit state indicates that the element is editable if its parent is. The false state indicates that the element is not editable.

This means that a contenteditable=false element within a contenteditable=true element should not be editable.

Furthermore, a contenteditable=true element within a contenteditable=true element should have its content editable. Meaning the answer to the question you linked is actually invalid (although when it was posted this may have been the case).

`ie9` - contenteditable false not working when parent editable

In IE it actually is working that the "false" flag is respected, but if you double-click on it, it goes into editmode (possibly because the double-click event bubbles up to the parent?).

My suggestion would be to put your non-editable content in an ::after element (since no browser will find a caret position inside it to allow it to be edited) like so:

#content{    border:1px solid black;    height:100px;}
.subContentEdit{ background:#87a476;}
.subContentEdit::after { content:'Not editable'; display:block; background:#ffd5d5;}
<div id="content" contenteditable="true">    <div class="subContentEdit">Editable</div>    Enter text here..</div>

HTML contenteditable with non-editable islands

One more idea that looks promising:

To use empty span with ::before { content:"caption"; } that should produce non editable block represented in in DOM as a node having no caret positions inside.

You can try it here http://jsfiddle.net/TwVzt/1/

But this approach is not free of problems (in my case): There is no way to declare ::before inline using style DOM attribute and so the whole set should be declared in CSS upfront.
But set of merge codes I have is pretty large, even unknown upfront in full in some use cases. Sigh.

Nevertheless putting this recipe here if someone will have better circumstances (known set of codes).

Selection and deletion problems with Non-Editable Span inside ContentEditable DIV

The challenge to this is to get IE11 to backspace from the right directly against the <span>.  Then the next backspace will select and highlight it.  This seems like such a simple objective, but IE11 just won't cooperate.  There should be a quick easy patch, right?  And so the bugs begin.

The approach I came up with is to walk the tree backwards to the first previous non-empty node, clearing the empty nodes between to appease IE, and then evaluate a few conditions.  If the caret should end up at the right side of the <span>, then do it manually (because IE won't) by creating a new range obj with the selection there at the end of the <span>.

online demo


I added an additional kludge for IE in the case that two spans are dragged against eachother.  For example, Field2Field3.  When you then backspace from the right onto Field3, then backspace once again to delete it, IE would jump the caret leftward over Field2.  Skip right over Field2.  grrr.  The workaround is to intercept that and insert a space between the pair of spans.  I wasn't confident you'd be happy with that.  But, you know, it's a workaround.  Anyway, that turned-up yet another bug, where IE changes the inserted space into two empty textnodes.  more grrr.  And so a workaround for the workaround.  See the non-isCollapsed code. 

CODE SNIPPET

var EditableDiv = document.getElementById('EditableDiv');
EditableDiv.onkeydown = function(event) { var ignoreKey; var key = event.keyCode || event.charCode; if (!window.getSelection) return; var selection = window.getSelection(); var focusNode = selection.focusNode, anchorNode = selection.anchorNode;
var anchorOffset = selection.anchorOffset;
if (!anchorNode) return
if (anchorNode.nodeName.toLowerCase() != '#text') { if (anchorOffset < anchorNode.childNodes.length) anchorNode = anchorNode.childNodes[anchorOffset] else { while (!anchorNode.nextSibling) anchorNode = anchorNode.parentNode // this might step out of EditableDiv to "justincase" comment node anchorNode = anchorNode.nextSibling } anchorOffset = 0 }
function backseek() {
while ((anchorOffset == 0) && (anchorNode != EditableDiv)) {
if (anchorNode.previousSibling) { if (anchorNode.previousSibling.nodeName.toLowerCase() == '#text') { if (anchorNode.previousSibling.nodeValue.length == 0) anchorNode.parentNode.removeChild(anchorNode.previousSibling) else { anchorNode = anchorNode.previousSibling anchorOffset = anchorNode.nodeValue.length } } else if ((anchorNode.previousSibling.offsetWidth == 0) && (anchorNode.previousSibling.offsetHeight == 0)) anchorNode.parentNode.removeChild(anchorNode.previousSibling)
else { anchorNode = anchorNode.previousSibling
while ((anchorNode.lastChild) && (anchorNode.nodeName.toUpperCase() != 'SPAN')) {
if ((anchorNode.lastChild.offsetWidth == 0) && (anchorNode.lastChild.offsetHeight == 0)) anchorNode.removeChild(anchorNode.lastChild)
else if (anchorNode.lastChild.nodeName.toLowerCase() != '#text') anchorNode = anchorNode.lastChild
else if (anchorNode.lastChild.nodeValue.length == 0) anchorNode.removeChild(anchorNode.lastChild)
else { anchorNode = anchorNode.lastChild anchorOffset = anchorNode.nodeValue.length //break //don't need to break, textnode has no children } } break } } else while (((anchorNode = anchorNode.parentNode) != EditableDiv) && !anchorNode.previousSibling) {} } }
if (key == 8) { //backspace if (!selection.isCollapsed) {
try { document.createElement("select").size = -1 } catch (e) { //kludge for IE when 2+ SPANs are back-to-back adjacent
if (anchorNode.nodeName.toUpperCase() == 'SPAN') { backseek() if (anchorNode.nodeName.toUpperCase() == 'SPAN') { var k = document.createTextNode(" ") // doesn't work here between two spans. IE makes TWO EMPTY textnodes instead ! anchorNode.parentNode.insertBefore(k, anchorNode) // this works anchorNode.parentNode.insertBefore(anchorNode, k) // simulate "insertAfter" } } }

} else { backseek()
if (anchorNode == EditableDiv) ignoreKey = true
else if (anchorNode.nodeName.toUpperCase() == 'SPAN') { SelectText(event, anchorNode) ignoreKey = true } else if ((anchorNode.nodeName.toLowerCase() == '#text') && (anchorOffset <= 1)) {
var prev, anchorNodeSave = anchorNode, anchorOffsetSave = anchorOffset anchorOffset = 0 backseek() if (anchorNode.nodeName.toUpperCase() == 'SPAN') prev = anchorNode anchorNode = anchorNodeSave anchorOffset = anchorOffsetSave
if (prev) { if (anchorOffset == 0) SelectEvent(prev)
else { var r = document.createRange() selection.removeAllRanges()
if (anchorNode.nodeValue.length > 1) { r.setStart(anchorNode, 0) selection.addRange(r) anchorNode.deleteData(0, 1) } else { for (var i = 0, p = prev.parentNode; true; i++) if (p.childNodes[i] == prev) break r.setStart(p, ++i) selection.addRange(r) anchorNode.parentNode.removeChild(anchorNode) } } ignoreKey = true } } } } if (ignoreKey) { var evt = event || window.event; if (evt.stopPropagation) evt.stopPropagation(); evt.preventDefault(); return false; } }
function SelectText(event, element) { var range, selection; EditableDiv.focus(); if (window.getSelection) { selection = window.getSelection(); range = document.createRange(); range.selectNode(element) selection.removeAllRanges(); selection.addRange(range); } else { range = document.body.createTextRange(); range.moveToElementText(element); range.select(); } var evt = (event) ? event : window.event; if (evt.stopPropagation) evt.stopPropagation(); if (evt.cancelBubble != null) evt.cancelBubble = true; return false; }
#EditableDiv {          height: 75px;          width: 500px;          font-family: Consolas;          font-size: 10pt;          font-weight: normal;          letter-spacing: 1px;          background-color: white;          overflow-y: scroll;          overflow-x: hidden;          border: 1px solid black;          padding: 5px;        }        #EditableDiv span {          color: brown;          font-family: Verdana;          font-size: 8.5pt;          min-width: 10px;          /*_width: 10px;*/          /* what is this? */        }        #EditableDiv p,        #EditableDiv br {          display: inline;        }
<div id="EditableDiv" contenteditable="true"> (<span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>Field1</span> < 500)  <span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>OR</span> (<span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>Field2</span> > 100 <span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>AND</span> (<span contenteditable='false' onclick='SelectText(event, this);' unselectable='on'>Field3</span> <= 200) )</div>


Related Topics



Leave a reply



Submit