在内容可编辑的新行上触发事件 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总结一下;人

仅供参考,这是在 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...");
}

Here is the JSFiddle demo

我已经在 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>

See Fiddle Here

旁注: 内容可编辑中换行符的行为似乎多种多样,但我在 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