I find it more comfortable to take a look at the code first:
jQuery(document).ready(function() {
var idCount = 0;
var divEditableMutationObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
manipulateAddedNode(mutation);
});
});
var childDivEditableMutationObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
manipulateChildContent(mutation);
});
});
var mutationObserverOptions = {childList: true, attributes: true, characterData: true};
divEditableMutationObserver.observe(jQuery("#contentEditableDiv")[0], mutationObserverOptions);
function manipulateChildContent(mutation){
console.log(mutation);
}
function manipulateAddedNode(mutation){
jqAddedNode = jQuery(mutation.addedNodes[0]);
if(!jqAddedNode.find("select").length){
childDivEditableMutationObserver.observe(jqAddedNode[0], mutationObserverOptions);
jqAddedNode.prepend(createTagSelector());
var addedNodeId = "content" + idCount + "e";
++idCount;
jqAddedNode.prop("id", addedNodeId);
}
}
function createTagSelector(){
tagSelector = jQuery(document.createElement("select"));
tagSelector.prop("contenteditable", false);
tagSelector.append("<option value='p'>p</option>");
tagSelector.append("<option value='div'>div</option>");
tagSelector.append("<option value='pre'>pre</option>");
return tagSelector;
}
jQuery("#contentEditableDiv").append("<p></p>");
});
#contentEditableDiv {
border: 1px solid black;
height: 200px;
width: 500px;
word-wrap: break-word;
overflow: auto;
}
#contentEditableDiv p{
border: 1px solid red;
margin-left: 5px;
margin-right: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="contentEditableDiv" contenteditable="true" ></div>
Explanation:
At first we initialise two MutationObserver divEditableMutationObserver
and childDivEditableMutationObserver
.
The divEditableMutationObserver
observes the the only contentEditableDiv
element and calls the function manipulateAddedNode
if a mutation has been observed.
The manipulateAddedNode
function adds a select
element and an id
to the node and adds the added element to the childDivEditableMutationObserver
(via observe
).
When you run the Stack Snippet the described behaviour is complied.
Here are the issues:
If you click inside the p
element and press enter a new p
element gets created and the childDivEditableMutationObserver
logs entirety 3 new mutation.
But this is horrible wrong:
- The
manipulateAddedNode
function never gets called. In reference to my last question you have to notice that in this type of circumstances with adding a newp
element themutation
of thedivEditableMutationObserver
records the already existingp
element with the idcontent0e
. This is also obvious, because the newp
element does not have aselect
element. - This is far more important: Because the
manipulateAddedNode
never gets called with the newp
element it should not get observed by thechildDivEditableMutationObserver
. With respect to the specification of theMutationObserver
it should only record mutations which are of child objects not the observed object itself or even siblings of the observed objects. But as you can see thetarget
attribute of the newly 3 logged mutations is<p>…</p>
(the new element). Or am I wrong? The most horrible issue: In the 2. of the 3 logged mutation of the new created
p
element aselect
element is recorded underremovedNodes
. However the newp
element never had aselect
element as a child:"removedNodes": { "0": <select contenteditable="false">…</select>, "item": /**ref:3**/, "length": 1 },
The 3. point is for me the most problematic, because in my js application the manipulateChildContent
should detect a removed select
element and deletes the whole parent p
element if the following query equals true:
mutation.removedNodes.length && mutation.removedNodes[0].nodeName == "SELECT"
It is obvious that the problem(s) has(/have) something todo with the creation of the new p
element, like it gets copied or something like that.
Questions:
- Like I described in the forelast sentence I need a way to determine that the removed element of an
p
paragraph element is an already EXISTINGselect
so the entirep
element gets deleted. How can I determine this in the circumstances described (the 2. mutation hits the requirements) ? - How the hell does Javascript creates the new
p
element? AND - Why does it gets recorded by the mutation observer ?
I appreciate your help!