无法创造范围

Rah*_*sai 3 javascript jquery

我正在尝试选择动态添加的时间戳 - 在contentEditable元素中按Enter键.

$('#content').on('keypress', function(e) {
  if (e.which === 13) {
    console.log('enter pressed');
    e.preventDefault();
    var range = window.getSelection().getRangeAt(0);
    var element = document.createElement('p');
    element.setAttribute("id", "uniqueIdentifier");
    var date = new Date().getTime();
    date = date.toString();
    console.log('date: ' + date);
    element.textContent = date;
    //element.innerHTML = '<br>';
    range.insertNode(element);
    var range2 = document.createRange();
    console.log('$(#content).text(): ' + $('#content').text());
    var startOffset = $('#content').text().indexOf(date);
    console.log('startOffset: ' + startOffset);
    range2.setStart(document.getElementById('uniqueIdentifier'), startOffset);
    range2.setEnd(document.getElementById('uniqueIdentifier'), startOffset + date.length);
    //        $('#content p.new').focus();
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id='content' contentEditable='true'>test</p>
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

Uncaught IndexSizeError: Failed to execute 'setStart' on 'Range': There is no child at offset 4.
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

Dhi*_*raj 11

有两种方法.传递DOM节点或传递节点的文本部分.如果您传递DOM节点,则应将开始和结束偏移量设置为0和1,以便像这样在DOM节点上创建范围

range.setStart(document.getElementById('uniqueIdentifier'), 0);
range.setEnd(document.getElementById('uniqueIdentifier'), 1);
Run Code Online (Sandbox Code Playgroud)

如果您给出文本节点部分,那么您必须给出文本节点的长度以在DOM节点的文本部分上创建一个范围,如下所示

var uid = document.getElementById('uniqueIdentifier');
range.setStart(uid.firstChild, 0); <-- firstChild refers to the text part of a DOM node
range.setEnd(uid.firstChild, uid.firstChild.length);
Run Code Online (Sandbox Code Playgroud)

你是混合两种方式.你可以像这样解决它

$('#content').on('keypress', function(e) {
  if (e.which === 13) {
    e.preventDefault();
    var date = new Date().getTime();
    date = date.toString();
    var range = window.getSelection().getRangeAt(0);
    var element = $('<p></p>')
                    .attr('class', 'uniqueIdentifier') 
                    .text(date);
    range.insertNode(element[0]); // the date node is added to the DIV at this stage
    var range2 = document.createRange();
    range2.setStart(element[0], 0); // <--- Give the entire date node starting at 0
    range2.setEnd(element[0], 1); // <--- Ending at 1 since there is only one node that you want a range of 
    var newNode = document.createElement("b"); // <--- I created a b element just so that the range is visible
    range2.surroundContents(newNode);
  }
});
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

$('#content').on('keypress', function(e) {
  if (e.which === 13) {
    e.preventDefault();
    var date = new Date().getTime();
    date = date.toString();
    var range = window.getSelection().getRangeAt(0);
    var element = $('<p></p>')
      .attr('class', 'uniqueIdentifier')
      .text(date);
    range.insertNode(element[0]);
    var range2 = document.createRange();
    range2.setStart(element[0], 0);
    range2.setEnd(element[0], 1);
    var newNode = document.createElement("b");
    newNode.style.color = getRandomColor(); // <-- Just so that range is visible
    range2.surroundContents(newNode);
  }
});

/* Courtesy: http://stackoverflow.com/a/1484514 */
function getRandomColor() {
  var letters = '0123456789ABCDEF'.split('');
  var color = '#';
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id='content' contentEditable='true'>test</p>
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案!谢谢,.firstChild 为我做到了。从对我的引用中不清楚我们必须在 span 元素上调用 .firstChild 来定义其中的文本。 (4认同)