在一个令人满意的人中使用无序(或有序)列表让我很头疼。
每当我想通过按 ENTER 两次结束编辑列表时,浏览器将关闭<ul />
,但会插入<p />
(Firefox)或<div />
(Chrome)标记包含<br />
。
的 Example here
我的目标是避免多余的<p />
或<div />
,而只关闭<ul />
。
我尝试修改Tim Down's解决方案,这会阻止浏览器在按 ENTER 时插入<p />
或<div />
,而是插入一个干净的<br />
标记。
的 Example here
不幸但是,在使用该解决方案时,<ul />
永远不会被浏览器关闭,因为只有<br />
标记插入 in <li />
项目。
所以我的问题是:
如何在最后一个空<ul />
按Enter键时插入节点或粘贴html来主动关闭<li />
?
更新: 如果问题很明显:我正在寻找一种方法来关闭<ul />
而不插入{{1} }或<p />
代码,只需插入好的旧<div />
答案 0 :(得分:6)
与您的尝试类似,我们会在用户按下Enter键时修改contenteditable:Demo
if (window.getSelection) { // w3c
$('div').keypress(function (e) {
var sel, node, children, br, range;
if (e.which == 13) {
sel = window.getSelection();
node = $(sel.anchorNode);
children = $(sel.anchorNode.childNodes);
// if nothing is selected and the caret is in an empty <li>
// (the browser seems to insert a <br> before we get called)
if (sel.isCollapsed && node.is('li') && (!children.length ||
(children.length == 1 && children.first().is('br')))) {
e.preventDefault();
// if the empty <li> is in the middle of the list,
// move the following <li>'s to a new list
if (!node.is(':last-child')) {
node.parent().clone(false)
.empty()
.insertAfter(node.parent())
.append(node.nextAll());
}
// insert <br> after list
br = $('<br>').insertAfter(node.parent());
// move caret to after <br>
range = document.createRange();
range.setStartAfter(br.get(0));
range.setEndAfter(br.get(0));
sel.removeAllRanges();
sel.addRange(range);
// remove <li>
node.remove();
}
}
});
} else if (document.selection) { // internet explorer
$('div').keypress(function (e) {
var range, node, children;
if (e.which == 13) {
range = document.selection.createRange();
node = $(range.parentElement());
children = $(range.parentElement().childNodes);
// if nothing is selected and the caret is in an empty <li>
// (the browser seems to insert a <br> before we get called)
if (!range.htmlText.length && node.is('li') && (!children.length ||
(children.length == 1 && children.first().is('br')))) {
e.preventDefault();
// if the empty <li> is in the middle of the list,
// move the following <li>'s to a new list
if (!node.is(':last-child')) {
node.parent().clone(false)
.empty()
.insertAfter(node.parent())
.append(node.nextAll());
}
// insert <br> after list
br = $('<br>').insertAfter(node.parent());
// move caret to after <br>
range = document.body.createTextRange();
range.moveToElementText(br.get(0));
range.collapse(false);
range.select();
// remove <li>
node.remove();
}
}
});
}
请注意,这不会处理用户在按Enter之前选择了某些内容的情况。如果你想处理这种情况,你需要弄清楚用户是否选择了<li>
的全部内容(这似乎不是一项简单的任务),如果是,请删除内容和对待它就像用户在空<li>
中按Enter键一样。
答案 1 :(得分:1)
我理解你的问题,但不清楚为什么存在这样的要求。澄清这方面可能会有所帮助。
无论如何,这是一个想法。为什么不替换或删除空的<div>
和<p>
标记。
$(document).ready(function(){
$("div").keyup(function(evt) {
$("div, p").filter( function() {
$this = $(this);
return !($.trim($(this).text()).length);
}).replaceWith('<br />');
});
});
工作示例: http://jsfiddle.net/4xyR2/9/
我注意到的一个问题是contenteditable
如何使用上述解决方案影响游标。我认为Chrome和Firefox需要<div>
和<p>
,以便他们可以跟踪<div>
中光标的位置。这来自我在测试时的观察,而不是对浏览器如何解释contenteditable
的深刻理解。
Chrome(24.0.1312.52米)似乎不喜欢替换。我在测试它时会看到奇怪的光标位置,但它有效。 Firefox(17.0.1)很好地处理了替换。
答案 2 :(得分:0)
没有Javascript,我能够锻炼的最好的是
HTML:
<div contenteditable="true">
<div>asdfasdf</div>
</div>
LESS:
div[contenteditable=true] {
outline: none;
&>p,
&>div {
margin: 0 0 0 30px;
display: list-item;
}
}
bin http://jsbin.com/idekix/6/edit
但这里有一些缺点,
Win8上的第一个也是非常大的FireFox 18.0.1,而不是将div
或p
标记作为新行插入,使用类似double br
的内容,
当您删除所有内容并启动类型并点击输入时,第二个发生了,不同的浏览器行为非常不同,Chrome将第一行插入contenteditable
容器的正文文本节点,然后放入每个新行进入div
,Opera 12.12可以更好地处理它,它永远不会允许删除最后div
个节点,IE9-10开始跳转并在你再次开始使用p
标签而不是{{1} (这甚至不是这样的灾难,只是不一致),但FireFox还没有尝试改变它的div
行为。还尝试使用IE10调试模式检查IE7-8,它与Opera相同,但它不是真正的浏览器。
它允许你插入空节点的第三个,说到Opera做的好工作,在Opera http://jsbin.com/uxesez/1/edit中看到这个bin,标记在这里更接近原始,并且它没有允许您插入空br
。
据说,所有测试都在Windows 8 64位平台上完成,Chrome 24.0.1312.56 m,FireFox 18.0.1,Opera 12.12和IE10通过IE调试栏模拟旧IE。承认在其他平台/版本上,事情可能会有所不同。
总结以上所有内容,li
具有非常好的浏览器支持范围http://caniuse.com/contenteditable,但是每个浏览器都有自己的实现,这是另一个独立的问题。因此,如果没有crossbrowser JavaScrpt麻烦你就无法使用它。另外,我的个人意见contenteditable
核心思想更适合像contenteditable
的轻量级替换,当它用作浏览器中几乎每个富文本编辑器的元素时。
在HTML5中,任何元素都可以编辑。这个功能很久以前就已经推出了,但现在已经被WHATWG(html当前规范)标准化了。使用一些JavaScript事件处理程序,您可以将网页转换为完整且快速的富文本编辑器。
下一步是我的拙见。在你的情况下,非常方便,正如我的意见,将使用真正的可编辑字段。我在这个bin http://jsbin.com/ojiyok/7/edit中做的非常多的原型版本仍然有待改进,但看起来它比真正的iframe
具有更可预测的行为,而且在这里您可以根据自己的需要更改UI浏览器一下子。