首页 > 解决方案 > 在 contenteditable div 中创建一个具有随机名称的新段落

问题描述

每次有人单击该Enter键时,我都想添加一个随机名称。例如:如果有人按下 Enter 键,它应该创建一个段落块,其名称与 Medium.com文本编辑器相同。

但像往常一样 contenteditable div 只是在Enter按下键时复制前一个元素。但我不想复制元素。我想创建一个具有唯一名称的新块。

在此处输入图像描述

.root {
  border: 1px solid #212121;
}
<div class="root" contenteditable>
  <p name="kLdnD" class="block">Block with random name</p>
  <p name="uIDlf" class="block">Second block</p>
</div>

标签: javascript

解决方案


以下代码依赖于浏览器在新行上复制可编辑 div 的最后一个子元素的事实。在 key down 时,我们处理还没有子元素的情况,我们确保第一个元素是一个段落,让浏览器自动创建更多段落。

为了设置新创建段落的 id 和名称,我们使用突变观察者 API 在添加段落时获得通知。

另一个特点是如果第一次击键是 Enter,我们添加的第二段。我们需要这个,因为浏览器显示一个空 div 和一个带有一个空段落的 div 相同。

<html>
<head>
<script>
    function loaded()
    {
        //  https://stackoverflow.com/questions/105034/how-to-create-guid-uuid
        function uuidv4() {
          return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
          });
        }

        const zzz = document.getElementById("zzz");
        zzz.onkeydown = function(e)
        {
            if(!zzz.children.length)
            {
                let element = document.createElement("p");
                element.innerHTML = "<br />";
                zzz.appendChild(element);
                if(e.code == "Enter")
                {
                    element = document.createElement("p");
                    element.innerHTML = "<br />";
                    zzz.appendChild(element);
                }
                window.getSelection().collapse(element, 0);
                e.preventDefault();
            }
        }
        const observer = new MutationObserver(function(mutationList, observer)
        {
            for(let ilength = mutationList.length, i = 0; i < ilength; ++i)
            {
                const addedNodes = mutationList[i].addedNodes;
                for(let jlength = addedNodes.length, j = 0; j < jlength; ++j)
                {
                    const node = addedNodes[j];
                    const randomNumber = uuidv4();
                    node.id = "pid" + randomNumber;
                    node.setAttribute("name", "pn" + randomNumber);
                }
            }
        });
        observer.observe(zzz, { childList: true });
    }
</script>
</head>
<body onload="javascript:loaded();">
<div id="zzz" contenteditable="true"></div>
</body>
</html>


推荐阅读