MutationObserver记录兄弟姐妹

时间:2016-10-13 23:21:37

标签: javascript jquery mutation-observers

我发现首先看一下代码会更舒服:

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>

说明:

首先我们初始化两个MutationObserver divEditableMutationObserverchildDivEditableMutationObserver

divEditableMutationObserver观察唯一的contentEditableDiv元素,如果观察到突变则调用函数manipulateAddedNode

manipulateAddedNode函数向节点添加select元素和id,并将添加的元素添加到childDivEditableMutationObserver(通过observe)。< / p>

运行Stack Snippet时,将遵循所描述的行为。

以下是问题:

如果您在p元素内单击并按Enter键,则会创建一个新的p元素,并且childDivEditableMutationObserver会记录整个3个新的突变。

但这是一个可怕的错误:

  1. 永远不会调用manipulateAddedNode函数。在提及我的last question时,您必须注意,在这种情况下,添加新的p元素,mutation的{​​{1}}会记录已存在的divEditableMutationObserver p标识为content0e的元素。这也很明显,因为新的p元素没有select元素。
  2. 这一点非常重要:因为manipulateAddedNode永远不会被新的p元素调用,所以childDivEditableMutationObserver不应该观察它。关于MutationObserver的规范,它应该只记录子对象的突变而不是被观察对象本身的突变,甚至是被观察对象的兄弟。但正如您所看到的,新记录的3个突变的target属性为<p>…</p>(新元素)。或者我错了吗?
  3. 最可怕的问题:在新创建的p元素的3个记录变异的2.中select元素记录在removedNodes下。但是,新的p元素从未在子元素中使用select元素:

    "removedNodes": {
        "0": <select contenteditable="false">…</select>,
        "item": /**ref:3**/,
        "length": 1
    },
    
  4. 第3点对我来说是最有问题的,因为在我的js应用程序中,manipulateChildContent应检测已删除的select元素并删除整个父p元素,如果以下查询等于真:

    mutation.removedNodes.length && mutation.removedNodes[0].nodeName == "SELECT"

    很明显,问题与新p元素的创建有一些共同点,就像它被复制一样或类似的东西。

    问题:

    1. 就像我在forelast句子中描述的那样,我需要一种方法来确定p段落元素的已删除元素是否已经存在select,因此整个p元素将被删除。如何在所描述的情况下确定这一点(2.突变符合要求)?
    2. Javascript如何创建新的p元素? AND
    3. 为什么变异观察者会记录它?
    4. 感谢您的帮助!

0 个答案:

没有答案