【问题标题】:Trigger event on new line in content editable div在内容可编辑的 div 中的新行上触发事件
【发布时间】:2015-10-28 02:49:04
【问题描述】:

我正在尝试侦听一个指示已在内容可编辑 div 中创建新行的事件。目的是在每次创建新的空行并且插入符号位于该行时,或者如果用户单击插入符号位置到当前空行时,最终向用户显示一些选项。

在我的书中似乎有四个事件会导致用户在可满足的 div 中换行:

  • 按回车键
  • 粘贴末尾有一个空的新行的内容
  • 单击导致插入符号(闪烁线)将位置移动到空行
  • 使用箭头键移动到新行

当然,在可满足的 div 中,新行对不同的浏览器意味着不同的东西,在 chrome 中,它似乎创建了 <div><br/></div> 标签,但是浏览了足够多的东西后,似乎其他浏览器可能会创建 <div><p></p></div> 或者 @987654323 @标签。

我现在已经尝试过几次了,只需要完成它。这真的是监听该 div 下添加的新元素的最佳方式,和/或检查插入符号位置当前是否在空的“新行”标签内。每次插入符号移动时检查似乎效率很低 - 有没有更好的方法来做到这一点?

总结 tldr;人

  • 有没有更好的方法来检查内容可编辑 div 中的新行?
  • 如何有效地触发基于此的事件?

仅供参考,这是在 Angular 上下文中,我也有 jQuery(答案可以选择使用或不使用这些库)。

----- 编辑-----

到目前为止,答案都集中在创建新行“事件”和监视这些事件上,也许轮询插入符号位置是确定插入符号是否在空行上的更可靠方法。

【问题讨论】:

    标签: jquery html css angularjs contenteditable


    【解决方案1】:

    到目前为止,其他答案讨论了监视在内容可编辑 div 中创建换行符的事件。然而,从目前的努力来看,这似乎不是一种可靠的方式来监控用户是否将插入符号带到了新行。

    尽管担心 setInterval 事件很笨重并且会增加开销,但也许这只是我的看法。我在 OSX 上的 Firefox 和 Chrome 中测试了以下内容。

    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 中注意到它会模仿该领域中的现有元素。即如果你使用&lt;div&gt;&lt;/div&gt;,firefox会使用&lt;div&gt;&lt;/div&gt;,如果你使用&lt;p&gt;&lt;/p&gt;,firefox也会这样做

    【讨论】:

      【解决方案2】:

      这就是我所做的:

      $("#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

      【讨论】:

      • 嘿@ahs 适用于 enter 事件,但不适用于通过粘贴内容或重新定位插入符号进入新行。 :)
      • @DavidAnderton 我更新了代码,现在单击空白行时会触发它:) 但是您能否更具体地说明粘贴内容时的含义?
      • “粘贴内容”是指在 div 中使用插入符号,使用 ctrl+v,右键单击即可使用粘贴选项,并在编辑菜单中使用粘贴选项。内容是text/plain,所以可能是从记事本粘贴了几段。
      • @DavidAnderton 哈哈,非常准确:P 我的意思是,目前如果我粘贴一些行,中间有一些空行,然后我点击空行,你会看到一个警报。但这似乎不是您在粘贴代码时所期望的行为,是吗?
      • 嘿嘿,以便更好地解释:我的意思是,如果您粘贴并且插入符号最终出现在空白行上,则应该触发该事件。 (即,插入符号以空行结束,单击、粘贴、使用箭头键或以其他方式触发事件)
      【解决方案3】:

      我已经在 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');
                      }
                  }
              }
          });
      

      【讨论】:

      • 嘿@tzach,在 OSX 或 iOS Safari 上使用 chrome 粘贴内容(包括新行)时,这似乎不起作用。此外,当使用箭头键导航到新行时,它不会被触发。
      【解决方案4】:

      这是你的开始。我什至不会费心去猜测不同的浏览器实现。相反,通过将焦点推送到隐藏的文本区域然后基于其中的换行符进行测试(例如 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

      【讨论】:

      • 在输入时按此工作,但在单击时它不适合我 - 而且由于焦点已从元素上移开,似乎无法通过使用箭头将插入符号移动到新行来进行测试键。另一个注意事项是它似乎在早餐时吃了丰富的内容并变成了纯文本。使用 Chrome 版本 44.0.2403.130(64 位)OSX
      猜你喜欢
      • 2021-06-08
      • 2016-09-02
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多