提问人:Emre Karayalcin 提问时间:12/3/2019 最后编辑:Run_ScriptEmre Karayalcin 更新时间:12/3/2019 访问量:1587
contenteditable 中的嵌套列表
Nested List within contenteditable
问:
我目前正在尝试在树层次结构中自动创建项目符号,当您按 Tab 键时,您将转到要点的子点。
它类似于Microsoft Word中的大纲。但是,我正在苦苦挣扎,因为目前从下面的代码中,我应该采取什么方法,我只能创建一个点列表,但我希望能够缩进一些点,它们将与项目符号一起向右移动。
function list() {
let ul = document.getElementById("ul");
let li = document.createElement("li");
ul.appendChild(li);
}
<div id="ul" contenteditable="true" class="editor" draggable="true" onfocus="list()" style="font-weight:normal;">
</div>
答:
1赞
Jenaro Calviño
12/3/2019
#1
如果我没看错的话,您只需要在父 ul 上设置一个填充,这很有趣,它们已经设置好了,如果您想进一步缩进它,您可以向其添加更多填充,但从您的示例来看,它不够清楚,您没有为 li, 另一方面,如果你想聚焦一个 div,你可能应该为它设置一个 TabIndex。
编辑:我之前没有发现您正在使用id为ul的div,您仍然可以添加一个内部子级li,但这没有多大意义,如果您仍然决定这样做,则可以将每个li子级设置为具有相同的边距,并将before属性设置为具有“*”
编辑2:
初始标记:
<div class="outline-editor">
<button>+ Add child</button>
<input type="text" name="content" id="add-text" />
<ul>
Items go here:
</ul>
</div>
<script>
const button = document.querySelector('button')
const input = document.querySelector('input')
const ul = document.querySelector('ul')
function addChild(li) {
let ul = li.querySelector('ul');
if (!ul) {
ul = document.createElement('ul')
li.appendChild(ul)
}
let childLi = document.createElement('li')
let childButton = document.createElement('button')
childButton.innerText = '+ Add child'
let childSpan = document.createElement('span')
childSpan.innerText = input.value;
childButton.addEventListener('click', () => {
addChild(childLi)
})
childLi.style.marginLeft = '15px'
childLi.appendChild(childSpan)
childLi.appendChild(childButton)
ul.appendChild(childLi)
}
function handleClick(e) {
let li = document.createElement('li')
let childButton = document.createElement('button')
childButton.innerText = '+ Add child'
let childSpan = document.createElement('span')
childSpan.innerText = input.value;
childButton.addEventListener('click', () => {
addChild(li)
})
li.style.marginLeft = '15px'
li.appendChild(childSpan)
li.appendChild(childButton)
ul.appendChild(li)
}
button.addEventListener('click', handleClick)
</script>
您可以检查代码笔上的行为:
https://codepen.io/jenaro94/pen/RwNwyBr
当然,您可以进一步设置每个 li 元素的样式,并且您可能应该使用模态来检查用户作为孩子对每个 li 的写入内容。
编辑 3:
好的,这是最后也是最后的编辑,希望这对你有用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<style>
.outline-editor {
margin: 100px auto;
}
ul {
position: relative;
}
button {
border: 1px solid black;
}
input {
border: none;
}
</style>
<div class="outline-editor">
<ul id="top-level">
Items go here:
<li>
<input type="text" name="content" id="add-text" />
</li>
</ul>
</div>
<script>
const input = document.querySelector('#add-text')
const ul = document.querySelector('#top-level')
function addChild(li) {
let ul = li.tagName === 'UL' ? li : li.querySelector('ul')
if (!ul) {
ul = document.createElement('ul')
li.appendChild(ul)
}
let childLi = document.createElement('li')
let text = document.createElement('input')
text.type = 'text'
text.rows = 1
text.cols = 10
text.focus()
text.addEventListener('keydown', e => {
e.preventDefault()
if (e.keyCode === 9) {
addChild(childLi)
} else if (e.keyCode === 13) {
addChild(li)
}
})
childLi.appendChild(text)
ul.appendChild(childLi)
}
function handleKeyDown(e) {
e.preventDefault();
e.stopPropagation();
let li = document.createElement('li')
if (e.keyCode === 9) {
addChild(this.parentElement)
} else if (e.keyCode === 13) {
addChild(this.parentElement.parentElement)
}
}
input.addEventListener('keydown', handleKeyDown)
</script>
</body>
</html>
评论
0赞
Emre Karayalcin
12/3/2019
是的,对不起,不是很清楚。我明白你的意思了。您认为最合适的方法是什么。
0赞
Jenaro Calviño
12/3/2019
好吧,如果你能更好地解释一切的目的是什么,也许我可以更好地帮助你,对于初学者来说,如果你要列出一个清单,我会使用 ul 或 ol 标签,另一方面,你想在 li 标签中插入什么?里面有文字吗?这是一个经典的待办事项列表应用程序吗?为什么不使用 onclick 事件而不是 focus 事件?试着让你的问题回答所有这些事情,我会尽力帮助你
0赞
Emre Karayalcin
12/3/2019
我的目标是创建一个大纲编辑器,以便在用户编写句子或段落时。然后,用户可以在他们之前输入的特定句子上添加点。我的任务将其描述为树层次结构。我特别不能使用jQuery。
0赞
Jenaro Calviño
12/3/2019
好的,现在,我将更改我的答案以尝试满足您的要求
0赞
Emre Karayalcin
12/3/2019
那太好了。我看到你在那里做了什么。但是,你可能误解了我,或者我没有解释得足够清楚。我把它看作是一个记事本,所以当你按 Tab 键时,你会移动到次要点,当你按回车键时,你会回到要点。
0赞
Mr. Polywhirl
12/3/2019
#2
我可以在按键键时添加一个新关卡,但它无法跟踪它在里面创建的节点......
const TAB_KEY = 9;
const ENTER_KEY = 13;
let editor = document.querySelector('.editor');
editor.appendChild(document.createElement('li')); // Add initial (for visibility)
editor.addEventListener('focus', (e) => {
//let ul = e.target;
//let li = document.createElement('li');
//ul.appendChild(li);
});
editor.addEventListener('keydown', (e) => {
var code = e.keyCode || e.which;
if (code == TAB_KEY) {
e.preventDefault(); // Stop treating it like an actual tab
let parent = e.target;
let ul = document.createElement('ul');
let li = document.createElement('li');
ul.appendChild(li);
parent.appendChild(ul);
moveCursorToEnd(li);
} else if (code == ENTER_KEY) {
e.preventDefault(); // Stop treating it like an actual line feed
let parent = e.target;
let li = document.createElement('li');
parent.appendChild(li);
moveCursorToEnd(li);
}
});
// See: https://stackoverflow.com/a/55811159/1762224
function moveCursorToEnd(el) {
el.focus();
document.execCommand('selectAll', false, null);
document.getSelection().collapseToEnd();
}
.editor {
font-weight: normal
}
<div class="editor" contenteditable="true" draggable="true"></div>
评论
0赞
Emre Karayalcin
12/3/2019
嗨,这正是我想要的。问题是我将 javascript 放在一个单独的文件中,用于 HTML,因此我通过 src 将其链接到 HTML。然而,它似乎仍然没有认出它。
上一个:将多级列表扩展到级别 2 和 3
下一个:水平多维列表
评论