1

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:

  1. 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 new p element the mutation of the divEditableMutationObserver records the already existing p element with the id content0e. This is also obvious, because the new p element does not have a select element.
  2. This is far more important: Because the manipulateAddedNode never gets called with the new p element it should not get observed by the childDivEditableMutationObserver. With respect to the specification of the MutationObserver 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 the target attribute of the newly 3 logged mutations is <p>…</p> (the new element). Or am I wrong?
  3. The most horrible issue: In the 2. of the 3 logged mutation of the new created p element a select element is recorded under removedNodes. However the new p element never had a select 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:

  1. 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 EXISTING select so the entire p element gets deleted. How can I determine this in the circumstances described (the 2. mutation hits the requirements) ?
  2. How the hell does Javascript creates the new p element? AND
  3. Why does it gets recorded by the mutation observer ?

I appreciate your help!

Community
  • 1
  • 1
goulashsoup
  • 2,639
  • 2
  • 34
  • 60
  • Difficult to follow what issue is? – guest271314 Oct 13 '16 at 23:30
  • I really make an effort that everybody can understand. I think it is possible with reading attentive! I even list them! – goulashsoup Oct 13 '16 at 23:33
  • 1
    Gather the effort made. Why are two `MutationObserver` instances needed? What are you trying to achieve? What is expected result? – guest271314 Oct 13 '16 at 23:36
  • Are you kdding my? -> *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:* !!! The `divEditableMutationObserver` only observes child of the `contentEditableDiv` and the `childDivEditableMutationObserver` only observes mutations of `p` elements inside the `contentEditableDiv`! – goulashsoup Oct 13 '16 at 23:39
  • No, not kidding. There appears to be one element at `html` at Question. Why would two `MutationObserver` instances be needed? The `MutationObserver` observing `contentEditable` element should observe all child nodes added or removed from the parent element. It is not necessary to attach a second `MutationObserver` to a child node of parent where `MutationObserver` is already observing all changes to the parent node. Unless missing something, and second `MutationObserver` observes nodes appended to an element other than `contentEditable` element? – guest271314 Oct 13 '16 at 23:41
  • Yes you are missing something: The 2. `MutationObserver` observes just the `p` elements not the whole `contentEditableDiv`. If you use the `subtree: true` option and only one `MutationObserver` it is harder to process the occurance of a mutation, because you must determine the further treatment in one function which is less readable and contravene the [Separation of concerns](https://en.wikipedia.org/wiki/Separation_of_concerns). Without `subtree: true` a `MutationObserver` only observes direct childes! – goulashsoup Oct 13 '16 at 23:46
  • The current `javascript` is not a simple matter to read and fully grasp what is occurring, or what should be occurring. Not sure how separation of concerns is related to the mutation of a single element, or a single elements' child nodes? Is requirement that if ` – guest271314 Oct 13 '16 at 23:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/125649/discussion-between-guest271314-and-goulashsoup). – guest271314 Oct 13 '16 at 23:53
  • Yes, but I question at first is about the wrong behavior of the `MutationObserver` objects, thats why I leaved it as a marginal note. Of course I could just one `MutationObserver` but then I would not ask about it. And I really think that this piece of js is not too complicated to understand. – goulashsoup Oct 13 '16 at 23:56
  • I use cascaded observers pretty often, but this question overall and the code inside seem needlessly convoluted. What is the ultimate goal from the user perspective, in simple terms? – wOxxOm Oct 14 '16 at 02:01
  • I think we can continue that discussion infinitely and talk past each other! The question like some other questions on StackOverflow is about the behaviour of the `MutationObserver` and not points to direct simple solution of a well described "goal"! *needlessly convoluted* -> I don´t think so, it is quite simple: A *parent* get attached to a `MutationObserver` so the `MutationObserver` observes *direct childs* and the *direct childs* get attached to another `MutationObserser` so this one can observe *childs* of the *direct childs*! – goulashsoup Oct 14 '16 at 09:47
  • Well, I've encountered strange behavior of MutationObserver a lot, but each time it turned out to be because of the flawed algorithm. Looking at how you mix jQuery where it's not needed, I've supposed your solution is buggy. Sorry for that. – wOxxOm Oct 15 '16 at 22:20

0 Answers0