JavaScript - 为在contenteditable div中编写的每个字母添加span

时间:2017-08-25 08:25:49

标签: javascript html css contenteditable

我想创建脚本,将<span>添加到contenteditable div的每个字母。例如:
如果您在可疑的div中撰写内容,则在HTML代码中,您会看到:

<div contenteditable="true">
    SomeText
</div>

我需要做些什么才能看到这样的事情:

<div contenteditable="true">
    <span>S</span>
    <span>o</span>
    <span>m</span>
    <span>e</span>
    <span>T</span>
    <span>e</span>
    <span>x</span>
    <span>t</span>
</div>  

我写了一些代码(使用Rangy),但它不起作用。你可以看到下面的代码,但我不推荐它,因为它很长,正如我所说,不起作用。

$('#Box').keypress(function() {
  setTimeout(function() {
    var selLenght = getCaretCharacterOffsetWithin(document.getElementById('Box'));

    var precedingChar = "",
      sel, range, precedingRange;
    sel = rangy.getSelection();
    range = sel.getRangeAt(0).cloneRange();
    range.setStart(document.getElementById('Box'), 0);
    sel.setSingleRange(range);
    sel.removeAllRanges();
    range.setStart(document.getElementById('Box'), selLenght - 21);
    sel.setSingleRange(range);
/*
    var newElem = document.createElement('span');
    newElem.className = 'test';
    $(newElem).html(range.extractContents());
    range.insertNode(newElem);
    $('#MainBox > span:empty').remove();
*/
    rangy.getSelection().move('character', 0);
  });
});

function getCaretCharacterOffsetWithin(element) {
    var caretOffset = 0;
    if (typeof window.getSelection != "undefined") {
        var range = window.getSelection().getRangeAt(0);
        var preCaretRange = range.cloneRange();
        preCaretRange.selectNodeContents(element);
        preCaretRange.setEnd(range.endContainer, range.endOffset);
        caretOffset = preCaretRange.toString().length;
    } else if (typeof document.selection != "undefined" && document.selection.type != "Control") {
        var textRange = document.selection.createRange();
        var preCaretTextRange = document.body.createTextRange();
        preCaretTextRange.moveToElementText(element);
        preCaretTextRange.setEndPoint("EndToEnd", textRange);
        caretOffset = preCaretTextRange.text.length;
    }
    return caretOffset;
}
div{
  width: 400px;
  height: 200px;
  border: 1px solid black;
}
<script src="https://github.com/timdown/rangy/blob/master/lib/rangy-core.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div contenteditable="true" id="Box"></div>

如何在JavaScript和/或JQuery中执行类似的操作和/或免费用于商业用途的外部库? 谢谢你的帮助。

3 个答案:

答案 0 :(得分:2)

我认为这就是你所需要的。

将“Id”设置为您的contenteditable div

然后编写这个简单的脚本......

var text = document.getElementById("contenteditableDiv");
var string = "SomeText";
string.split("");
var i = 0, length = string.length;
for (i; i < length; i++) {
    text.innerHTML += "<span>" + string[i] + "</span>";
}

https://jsfiddle.net/f85zsLdf/3/如果你需要它......

请告诉我这是否对您有所帮助!

答案 1 :(得分:2)

更新:

使用此Github solution我解决了开头出现的字符问题。

这对你有帮助吗?

var myDiv = document.getElementById("yourDiv");

function doJob(){
  var myDivContent = myDiv.textContent.trim();
  var myDivContentSplit = myDivContent.split("");
  myDiv.innerHTML = "";
  for(var i=0; i<myDivContentSplit.length ; i++){
    var newSpan = document.createElement('span')
    newSpan.innerHTML = myDivContentSplit[i];
    myDiv.appendChild(newSpan);
  }
  setEndOfContenteditable(myDiv);
}

myDiv.addEventListener("keyup", doJob);


function setEndOfContenteditable(contentEditableElement)
{
    var range,selection;
    if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+
    {
        range = document.createRange();//Create a range (a range is a like the selection but invisible)
        range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
        range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
        selection = window.getSelection();//get the selection object (allows you to change selection)
        selection.removeAllRanges();//remove any selections already made
        selection.addRange(range);//make the range you have just created the visible selection
    }
    else if(document.selection)//IE 8 and lower
    { 
        range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible)
        range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range
        range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
        range.select();//Select the range (make it the visible selection
    }
}
div{
  border: 1px solid #999;
  padding: 10px;
}
span{
  background-color: #ea0;
}
<div contenteditable="true" id="yourDiv">
    SomeText
</div>

答案 2 :(得分:2)

使用jQuery,您可以执行以下操作,还要注意我们需要一些辅助函数来管理光标位置。

&#13;
&#13;
<div class="container">
            <h3 class="listTitle">Do Now</h3>

            <!-- Uncompleted tasks -->
            <ul class="todo" id="todo" list="todo1"></ul>


            <!-- Completed tasks -->
            <ul class="todo" id="completed" list="completed1"></ul>
</div>
&#13;
var box = $('#Box');
var button = $('button');

box.on('input', function(e) {
  restoreCaret = saveCaretPosition(this);
  box.html(wrapLetters(box.text()));
  restoreCaret();
});

var textContent = '';
button.on('mousedown', function() {
  button.text('Hide HTML');
  textContent = box.text();
  box.text(box.html());
});
button.on('mouseup', function() {
  button.text('Show HTML');
  box.text(textContent);
  box.html(wrapLetters(textContent));
});


/* HELPERS */
function wrapLetters(textContent) {
  return textContent.split('').map(function(letter) {
    return '<span>' + letter + '</span>';
  }).join('');
}

function saveCaretPosition(context) {
  var selection = window.getSelection();
  var range = selection.getRangeAt(0);
  range.setStart(context, 0);
  var len = range.toString().length;

  return function restore() {
    var pos = getTextNodeAtPosition(context, len);
    selection.removeAllRanges();
    var range = new Range();
    range.setStart(pos.node, pos.position);
    selection.addRange(range);

  }
}

function getTextNodeAtPosition(root, index) {
  var lastNode = null;

  var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, function next(elem) {
    if (index > elem.textContent.length) {
      index -= elem.textContent.length;
      lastNode = elem;
      return NodeFilter.FILTER_REJECT
    }
    return NodeFilter.FILTER_ACCEPT;
  });
  var c = treeWalker.nextNode();
  return {
    node: c ? c : root,
    position: c ? index : 0
  };
}
&#13;
#Box {
  width: 400px;
  height: 100px;
  border: 1px solid black;
}
&#13;
&#13;
&#13;