在contenteditable div中的插入符号中以特殊字符开头

Sex*_*ast 16 javascript jquery contenteditable

我有一个contenteditable div,我需要在当前的插入位置知道这个词.我试过这个解决方案,但问题是,它不能识别像@和的特殊字符~.因此,如果一个单词开始~,就像~fool,我正在得到fool,而我期待~fool.所以我尝试修改解决方案时考虑到如果在移回选择后,遇到的字符不是空格,我会继续向后移动直到遇到空格.这将成为选择的开始.同样地,我会继续前进,直到找到一个空格,这标志着选择的结束.然后选择会给我这个词.为了获得插入位置,我使用了这个解决方案.结合起来,我的代码现在看起来像这样:

function getCaretPosition(editableDiv) {
  var caretPos = 0,
    sel, range;
  if (window.getSelection) {
    sel = window.getSelection();
    if (sel.rangeCount) {
      range = sel.getRangeAt(0);
      if (range.commonAncestorContainer.parentNode == editableDiv) {
        caretPos = range.endOffset;
      }
    }
  } else if (document.selection && document.selection.createRange) {
    range = document.selection.createRange();
    if (range.parentElement() == editableDiv) {
      var tempEl = document.createElement("span");
      editableDiv.insertBefore(tempEl, editableDiv.firstChild);
      var tempRange = range.duplicate();
      tempRange.moveToElementText(tempEl);
      tempRange.setEndPoint("EndToEnd", range);
      caretPos = tempRange.text.length;
    }
  }
  return caretPos;
}

function getCurrentWord() {
    var sel, word = "";
    if (window.getSelection && (sel = window.getSelection()).modify) {
        var selectedRange = sel.getRangeAt(0);
        sel.collapseToStart();
        sel.modify("move", "backward", "word");

        while (sel.toString() != " " && getCaretPosition($("#editor").get(0)) != 0) {
            sel.modify("move", "backward", "character");
            (sel = window.getSelection()).modify;
        }
        sel.modify("move", "forward", "character");      
        sel.modify("extend", "forward", "word");
        word = sel.toString();

        // Restore selection
        sel.removeAllRanges();
        sel.addRange(selectedRange);
    } else if ((sel = document.selection) && sel.type != "Control") {
        var range = sel.createRange();
        range.collapse(true);
        range.expand("word");
        word = range.text;
    }
    return word;
}

$(function () {

    $(document).on('keyup keydown paste cut mouseup',"#editor", function () {
        var word = getCurrentWord();
        console.log(word);
    });
});
Run Code Online (Sandbox Code Playgroud)

然而,这根本不起作用.那是问题.1.问题2是,即使图片中有图像并且用户点击图片,处理程序仍然会在图像之前返回最后一个单词,而我期待一个空白字符串.任何人都可以帮我解决这两个问题吗?

Tus*_*har 6

我修改了getCurrentWord()函数以使用基本的String方法从插入符号位置获取单词.该函数接受元素和位置,并返回该位置的单词.

以下是更新的功能.

function getCurrentWord(el, position) {
    // Get content of div
    var content = el.textContent;

    // Check if clicked at the end of word
    position = content[position] === ' ' ? position - 1 : position;

    // Get the start and end index
    var startPosition = content.lastIndexOf(' ', position);
    var endPosition = content.indexOf(' ', position);

    // Special cases
    startPosition = startPosition === content.length ? 0 : startPosition;
    endPosition = endPosition === -1 ? content.length : endPosition;

    return content.substring(startPosition + 1, endPosition);
}
Run Code Online (Sandbox Code Playgroud)

该函数首先获取元素的内容.接下来,它会检查用户是否点击在词的结尾,如果是,那么从位置减去一个,以便indexOflastIndexOf将在太空正常工作.

对于开始和结束位置,有两个特殊情况需要处理.首先,单击最后一个元素.为此,startPosition-1在最后一个单词后面没有空格.

其次,当点击第一个单词时,endPosition将是-1因为在第一个单词之前可能没有空格.

即使在最后一个字符之后的第一个字符和空格之前有空格,这两个条件也会起作用.

indexOflastIndexOf用于查找单词前后的空格,使用这些索引substring将在该位置给出单词.

这是现场演示测试.

$(function() {
  function getCaretPosition(editableDiv) {
    var caretPos = 0,
      sel, range;
    if (window.getSelection) {
      sel = window.getSelection();
      if (sel.rangeCount) {
        range = sel.getRangeAt(0);
        if (range.commonAncestorContainer.parentNode == editableDiv) {
          caretPos = range.endOffset;
        }
      }
    } else if (document.selection && document.selection.createRange) {
      range = document.selection.createRange();
      if (range.parentElement() == editableDiv) {
        var tempEl = document.createElement("span");
        editableDiv.insertBefore(tempEl, editableDiv.firstChild);
        var tempRange = range.duplicate();
        tempRange.moveToElementText(tempEl);
        tempRange.setEndPoint("EndToEnd", range);
        caretPos = tempRange.text.length;
      }
    }
    return caretPos;
  }

  function getCurrentWord(el, position) {
    var word = '';

    // Get content of div
    var content = el.textContent;

    // Check if clicked at the end of word
    position = content[position] === ' ' ? position - 1 : position;

    // Get the start and end index
    var startPosition = content.lastIndexOf(' ', position);
    startPosition = startPosition === content.length ? 0 : startPosition;
    var endPosition = content.indexOf(' ', position);
    endPosition = endPosition === -1 ? content.length : endPosition;

    return content.substring(startPosition + 1, endPosition);
  }


  $('#editor').on('keyup keydown paste cut mouseup', function() {
    var caretPosition = getCaretPosition(this);
    var word = getCurrentWord(this, caretPosition);
    console.log(word);
  });
});
Run Code Online (Sandbox Code Playgroud)
div {
  font-size: 18px;
  line-height: 1.5em;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="editor" contenteditable>



  Lorem !p$um dolor $!t @met, con$ectetur @d!p!$!c!ng el!t, $ed do e!u$mod tempor !nc!d!dunt ut l@bore et dolore m@gn@ @l!qu@. Ut en!m @d m!n!m ven!@m, qu!$ no$trud exerc!t@t!on ull@mco l@bor!$ n!$! ut @l!qu!p ex e@ commodo con$equ@t. Du!$ @ute !rure dolor
  !n reprehender!t !n volupt@te vel!t e$$e c!llum dolore eu fug!@t null@ p@r!@tur.
</div>
Run Code Online (Sandbox Code Playgroud)

  • 还有很多错误.例如,在你的小提琴中给出的示例内容中,如果你单击第三个单词 - dolor,并执行`CTRL-B`使其变为粗体,然后再次单击它,它会开始给出错误的单词.如果您双击一个单词来选择它,而不是记录该单词,则会记录错误的单词. (2认同)

Bry*_*son 2

这是一个非常简单的例子。有一个带有示例文本的 div:

<div contenteditable onclick="getCaretCharacterOffsetWithin(this)">some ~test content</div>
Run Code Online (Sandbox Code Playgroud)

这是脚本。当我们单击 div 时,无论光标落在哪里,我们都会获取当前位置并吐出我们所在的单词。该单词可以包含特殊字符,并且仅用空格分隔。

function getCaretCharacterOffsetWithin(element) {
    var caretOffset = 0;
    var doc = element.ownerDocument || element.document;
    var win = doc.defaultView || doc.parentWindow;
    var sel;
    if (typeof win.getSelection != "undefined") {
        sel = win.getSelection();
        if (sel.rangeCount > 0) {
            var range = win.getSelection().getRangeAt(0);
            var preCaretRange = range.cloneRange();
            preCaretRange.selectNodeContents(element);
            preCaretRange.setEnd(range.endContainer, range.endOffset);
            caretOffset = preCaretRange.toString().length;
        }
    } else if ( (sel = doc.selection) && sel.type != "Control") {
        var textRange = sel.createRange();
        var preCaretTextRange = doc.body.createTextRange();
        preCaretTextRange.moveToElementText(element);
        preCaretTextRange.setEndPoint("EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
    }
  console.log('caretOffset', caretOffset);
  word = getWordAtPosition(caretOffset, element);
  console.log('word', word);
    return caretOffset;
}

function getWordAtPosition(position, element) {
  var total_text = element.innerHTML;
  var current_word = "";
  var i = 0;
  var word_found = false;
  while(i < total_text.length) {
    if(total_text[i] != ' ')
      current_word += total_text[i];
    else if(word_found)
      return current_word;
    else
      current_word = "";
    if(i == position)
      word_found = true;
    i++;
  }
  return current_word;
}
Run Code Online (Sandbox Code Playgroud)

下面是它的工作示例:

https://codepen.io/anon/pen/dWdyLV