在内容可编辑的新行上触发事件 div
Trigger event on new line in content editable div
我正在尝试侦听一个事件,该事件指示已在可编辑内容 div 中创建了一个新行。目的是在每次创建新的空行并且插入符号位于该行上时,或者如果用户单击插入符号位置到当前空行时,最终向用户显示一些选项。
在我的书中,似乎有四个事件会导致用户在可满足的内容中换行 div:
- 按下回车键
- 粘贴末尾有空换行的内容
- 单击导致插入符号(闪烁线)将位置移动到空行
- 使用方向键移动到新行
当然,在一个令人满意的 div 中,新行对不同的浏览器意味着不同的东西,在 chrome 中,它似乎创建了 <div><br/></div>
标签,但是浏览了 SO 似乎足够了其他浏览器可能会创建 <div><p></p></div>
或 <span>
标签。
我现在已经尝试解决这个问题好几次了,但必须完成它。这真的是监听在 div、and/or 下添加的新元素的最佳方法吗?检查插入符位置当前是否在空 'new line' 标记内。每次插入符号移动时都进行检查似乎效率很低 - 有更好的方法吗?
为tldr总结一下;人
- 是否有更好的方法来检查内容可编辑 div 中的新行?
- 我如何有效地触发事件?
仅供参考,这是在 Angular 上下文中,我也有 jQuery(答案可以选择使用或不使用这些库)。
-----编辑-----
到目前为止,答案都集中在创建新行 'events' 和监视这些事件上,也许轮询插入符号位置是确定插入符号是否在空行上的更可靠方法。
这是我做的:
$("#main").keyup(function (e) {
if (e.which == 13) {
doSomething();
}
});
$("#main").on("click", "div:has(br)", function () {
doSomething();
});
$("#main").on("paste", function () {
setTimeout(function () {
debugger;
if ($('#main').children().last().children().last().has('br').length >0) {
doSomething();
}
}, 100);
});
function doSomething(){
alert("new line...");
}
我已经在 Chrome 和 Edge 上测试了这段代码。
当我从记事本复制和粘贴时,Edge 删除了空行。
http://codepen.io/tzach/pen/XbGWjZ?editors=101
angular
.module('app', [])
.directive('contenteditable', function ($timeout) {
return {
link: function($scope, element, attrs) {
element.css('white-space', 'pre');
element.on('keypress', function (e) {
if (e.keyCode === 13) {
$timeout(function () {
onNewLine();
}, 100);
}
});
element.on('paste', function (e) {
$timeout(function () {
var text = element.text();
var textRows = text.split('\n');
var html = element.html();
var htmlRows = html.split('<br>');
if (textRows[textRows.length - 1].trim() == '' ||
htmlRows[htmlRows.length - 1].trim() == '') {
onNewLine();
}
},0);
});
element.on('click', function(e) {
var html = e.target.innerHTML;
var text = e.target.innerText;
if (text === '\n' || html.toLowerCase() === '<br>') {
onNewLine();
}
});
function onNewLine() {
alert('new empty line');
}
}
}
});
到目前为止,其他答案讨论了监视在可编辑内容中创建换行符的事件 div。然而,从目前的努力来看,这似乎不是一种可靠的方式来监控用户是否将插入符号换行。
尽管担心 setInterval 事件很笨重并且会增加开销,但也许这只是我的看法。我已经在 Firefox 和 Chrome OSX 上测试了以下内容。
function getNewLines() {
console.log(document.getSelection());
if (document.getSelection().anchorNode) {
var node = document.getSelection().anchorNode;
var nodeContents = "";
if (node.innerHTML) {
nodeContents = node.innerHTML.toLowerCase();
} else {
nodeContents = node.innerHTML;
}
if (nodeContents !== undefined) {
if (nodeContents === "" || nodeContents == "<br>" || nodeContents ==
"<br/>" || nodeContents.substr(nodeContents.length - 5) == "<br/>" ||
nodeContents.substr(nodeContents.length - 4) == "<br>") {
console.log("you are on a new line :]");
} else {
console.log('nope not a new line');
}
} else {
console.log('nice try, but no not a new line');
}
}
}
setInterval(getNewLines, 100);
<div contenteditable="true">
<p>Lets get started!</p>
</div>
旁注: 内容可编辑中换行符的行为似乎多种多样,但我在 firefox 中注意到它会模仿该字段中的现有元素。即,如果您使用 <div></div>
,firefox 将使用 <div></div>
,如果您使用 <p></p>
,firefox 将执行相同的操作
这是您的开始。我什至懒得去猜测不同的浏览器实现。相反,通过将焦点推到隐藏的文本区域然后根据其中的换行符进行测试来填充它(例如 textarea.value.match(/\n$/)
)。
这应该可以处理所有用例,剩下的只是通过范围伪造插入符和选择。有一些插件就是为了这个目的而存在的。
JavaScript
var contentEditable = document.querySelector('.content pre'),
textarea = document.querySelector('.content textarea');
contentEditable.addEventListener('click', function() {
textarea.focus();
contentEditable.classList.add('pseudo-focus');
});
textarea.addEventListener('keyup', function(e) {
contentEditable.innerText = textarea.value;
if (textarea.value.match(/\n$/)) {
alert('newline');
}
});
HTML
<div class="content">
<pre id="editable" contenteditable></pre>
<textarea></textarea>
</div>
JSFiddle Example
我正在尝试侦听一个事件,该事件指示已在可编辑内容 div 中创建了一个新行。目的是在每次创建新的空行并且插入符号位于该行上时,或者如果用户单击插入符号位置到当前空行时,最终向用户显示一些选项。
在我的书中,似乎有四个事件会导致用户在可满足的内容中换行 div:
- 按下回车键
- 粘贴末尾有空换行的内容
- 单击导致插入符号(闪烁线)将位置移动到空行
- 使用方向键移动到新行
当然,在一个令人满意的 div 中,新行对不同的浏览器意味着不同的东西,在 chrome 中,它似乎创建了 <div><br/></div>
标签,但是浏览了 SO 似乎足够了其他浏览器可能会创建 <div><p></p></div>
或 <span>
标签。
我现在已经尝试解决这个问题好几次了,但必须完成它。这真的是监听在 div、and/or 下添加的新元素的最佳方法吗?检查插入符位置当前是否在空 'new line' 标记内。每次插入符号移动时都进行检查似乎效率很低 - 有更好的方法吗?
为tldr总结一下;人
- 是否有更好的方法来检查内容可编辑 div 中的新行?
- 我如何有效地触发事件?
仅供参考,这是在 Angular 上下文中,我也有 jQuery(答案可以选择使用或不使用这些库)。
-----编辑-----
到目前为止,答案都集中在创建新行 'events' 和监视这些事件上,也许轮询插入符号位置是确定插入符号是否在空行上的更可靠方法。
这是我做的:
$("#main").keyup(function (e) {
if (e.which == 13) {
doSomething();
}
});
$("#main").on("click", "div:has(br)", function () {
doSomething();
});
$("#main").on("paste", function () {
setTimeout(function () {
debugger;
if ($('#main').children().last().children().last().has('br').length >0) {
doSomething();
}
}, 100);
});
function doSomething(){
alert("new line...");
}
我已经在 Chrome 和 Edge 上测试了这段代码。 当我从记事本复制和粘贴时,Edge 删除了空行。
http://codepen.io/tzach/pen/XbGWjZ?editors=101
angular
.module('app', [])
.directive('contenteditable', function ($timeout) {
return {
link: function($scope, element, attrs) {
element.css('white-space', 'pre');
element.on('keypress', function (e) {
if (e.keyCode === 13) {
$timeout(function () {
onNewLine();
}, 100);
}
});
element.on('paste', function (e) {
$timeout(function () {
var text = element.text();
var textRows = text.split('\n');
var html = element.html();
var htmlRows = html.split('<br>');
if (textRows[textRows.length - 1].trim() == '' ||
htmlRows[htmlRows.length - 1].trim() == '') {
onNewLine();
}
},0);
});
element.on('click', function(e) {
var html = e.target.innerHTML;
var text = e.target.innerText;
if (text === '\n' || html.toLowerCase() === '<br>') {
onNewLine();
}
});
function onNewLine() {
alert('new empty line');
}
}
}
});
到目前为止,其他答案讨论了监视在可编辑内容中创建换行符的事件 div。然而,从目前的努力来看,这似乎不是一种可靠的方式来监控用户是否将插入符号换行。
尽管担心 setInterval 事件很笨重并且会增加开销,但也许这只是我的看法。我已经在 Firefox 和 Chrome OSX 上测试了以下内容。
function getNewLines() {
console.log(document.getSelection());
if (document.getSelection().anchorNode) {
var node = document.getSelection().anchorNode;
var nodeContents = "";
if (node.innerHTML) {
nodeContents = node.innerHTML.toLowerCase();
} else {
nodeContents = node.innerHTML;
}
if (nodeContents !== undefined) {
if (nodeContents === "" || nodeContents == "<br>" || nodeContents ==
"<br/>" || nodeContents.substr(nodeContents.length - 5) == "<br/>" ||
nodeContents.substr(nodeContents.length - 4) == "<br>") {
console.log("you are on a new line :]");
} else {
console.log('nope not a new line');
}
} else {
console.log('nice try, but no not a new line');
}
}
}
setInterval(getNewLines, 100);
<div contenteditable="true">
<p>Lets get started!</p>
</div>
旁注: 内容可编辑中换行符的行为似乎多种多样,但我在 firefox 中注意到它会模仿该字段中的现有元素。即,如果您使用 <div></div>
,firefox 将使用 <div></div>
,如果您使用 <p></p>
,firefox 将执行相同的操作
这是您的开始。我什至懒得去猜测不同的浏览器实现。相反,通过将焦点推到隐藏的文本区域然后根据其中的换行符进行测试来填充它(例如 textarea.value.match(/\n$/)
)。
这应该可以处理所有用例,剩下的只是通过范围伪造插入符和选择。有一些插件就是为了这个目的而存在的。
JavaScript
var contentEditable = document.querySelector('.content pre'),
textarea = document.querySelector('.content textarea');
contentEditable.addEventListener('click', function() {
textarea.focus();
contentEditable.classList.add('pseudo-focus');
});
textarea.addEventListener('keyup', function(e) {
contentEditable.innerText = textarea.value;
if (textarea.value.match(/\n$/)) {
alert('newline');
}
});
HTML
<div class="content">
<pre id="editable" contenteditable></pre>
<textarea></textarea>
</div>