【问题标题】:How can I get the line that is being clicked on in a contenteditable environment?如何在 contenteditable 环境中获得被点击的行?
【发布时间】:2021-02-27 07:55:34
【问题描述】:

我是 HTML/JS 的新手,我正在尝试将文本编辑器作为一个小项目。 如果我没有清楚地解释我的想法,请原谅我。

假设我的 contenteditable div 环境中有以下文本,并让 | 代表光标(就像在大多数编辑器中一样):

hi this is some text
here is some mor|e text
hello, world!

我怎样才能返回文本“这里还有一些文本”?

我正在使用 jQuery,我想我想使用 onClick 处理程序,但这不会响应用于导航的箭头键。我需要什么样的事件处理程序?到目前为止,我已经解析了文本以替换 div 分隔符,但我对如何继续有点迷茫。 你会建议做什么? (一般链接/建议也可以,我正在尝试通过这个项目了解更多信息)

编辑,这是我的 html:

<div id="editor" class="editor" contenteditable="true"></div>

这是 JS:

$(document).on('keydown', '.editor', function(e){
    //detect 'tab' key
    if(e.keyCode == 9){
        //add tab
        document.execCommand('insertHTML', false, '&#009');
        //prevent focusing on next element
        e.preventDefault()
    }
    var text = $("#editor").html();

    console.log("MYLITERAL:" + text);
    // parse the string :)
    // for the div tags, replacing them with \n
    var tmp = text.replace(/<div>/g, "");
    tmp = tmp.replace(/<\/div>/g, "");
    tmp = tmp.replace(/<br>/g, "\n");
    console.log(tmp);
    document.getElementById("demo").innerHTML = tmp;
});

【问题讨论】:

标签: javascript html jquery css


【解决方案1】:

您可以尝试以下方法:

var strO, endO, lstEle;

function selectRange(start, end, this_){
    var el = this_,sPos = start,ePos = end;
    var charIndex = 0, range = document.createRange();
    range.setStart(el, 0);
    range.collapse(true);
    var nodeStack = [el], node, foundStart = false, stop = false;
    while (!stop && (node = nodeStack.pop())) {
        if (node.nodeType == 3) {
            var nextCharIndex = charIndex + node.length;
            if (!foundStart && sPos >= charIndex && sPos <= nextCharIndex) {
                range.setStart(node, sPos - charIndex);
                foundStart = true;
            }
            if (foundStart && ePos >= charIndex && ePos <= nextCharIndex) {
                range.setEnd(node, ePos - charIndex);
                stop = true;
            }
            charIndex = nextCharIndex;
        } else {
            var i = node.childNodes.length;
            while (i--) {
                nodeStack.push(node.childNodes[i]);
            }
        }
    }
    var s = (window.getSelection) ? window.getSelection() : document.selection;
    if(window.getSelection) {
        s.removeAllRanges();
        s.addRange(range);
    } else {
        range.select();
    }
}

// node_walk: walk the element tree, stop when func(node) returns false
function node_walk(node, func) {
  var result = func(node);
  for(node = node.firstChild; result !== false && node; node = node.nextSibling){
    result = node_walk(node, func);
    lstEle = node;
  }
  return result;
};

// getCaretPosition: return [start, end] as offsets to elem.textContent that
//   correspond to the selected portion of text
//   (if start == end, caret is at given position and no text is selected)
function getCaretPosition(elem) {
    
    strO = 0, endO = 0, lstEle = elem;
    
  var sel = window.getSelection();
  var cum_length = [0, 0];

  if(sel.anchorNode == elem)
    cum_length = [sel.anchorOffset, sel.extentOffset];
  else {
    var nodes_to_find = [sel.anchorNode, sel.extentNode];
    if(!elem.contains(sel.anchorNode) || !elem.contains(sel.extentNode))
      return undefined;
    else {
      var found = [0,0];
      var i;
      node_walk(elem, function(node) {
        for(i = 0; i < 2; i++) {
          if(node == nodes_to_find[i]) {
            found[i] = true;
            if(found[i == 0 ? 1 : 0])
              return false; // all done
          }
        }

        if(node.textContent && !node.firstChild) {
          for(i = 0; i < 2; i++) {
            if(!found[i])
              cum_length[i] += node.textContent.length;
          }
        }
      });
      strO = cum_length[0];
      endO = strO + lstEle.textContent.length;
      cum_length[0] += sel.anchorOffset;
      cum_length[1] += sel.extentOffset;
    }
  }
  if(cum_length[0] <= cum_length[1])
    return cum_length;
  return [cum_length[1], cum_length[0]];
}

var update = function() {
    $('#test').html(getCaretPosition(this)+' '+strO+' '+endO);
    selectRange(strO, endO, this);
    $('#test').append('<br>'+window.getSelection().toString());
};
$('#editor').on("mouseup keydown keyup", update);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="editor" class="editor" contenteditable="true">hi this is some text<br>here is some more text<br>hello, world!</div>
<div id="test">test</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    相关资源
    最近更新 更多