【问题标题】:JavaScript - Add span to each letter written in contenteditable divJavaScript - 将跨度添加到以 contenteditable div 编写的每个字母
【发布时间】:2018-02-03 06:13:33
【问题描述】:

我想创建脚本,将<span> 添加到 contenteditable div 的每个字母。例如:
如果你在 contenteditable 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 和/或免费用于商业用途的外部库中执行类似操作?
感谢您的帮助。

【问题讨论】:

  • 例如,在按下提交按钮后,您是否需要在按键时执行此操作?您需要contentediable div 还是可以使用textarea
  • 我在按键事件和 contenteditable div 中需要这个

标签: javascript html css contenteditable


【解决方案1】:

我想这就是你需要的。

将“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/如果你需要...

如果这对您有帮助,请告诉我!

【讨论】:

    【解决方案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>

    【讨论】:

    • 好主意,但每个写入的字符都出现在行首。
    • 好话邀请我在 Github gist.github.com/al3x-edge/1010364 上查看这个有趣的代码并更新了我的帖子。
    • 好多了。我很难决定使用哪个答案。
    • 请注意,在这种情况下,如果您从文本中间开始书写,则会在末尾显式设置光标
    【解决方案3】:

    使用 jQuery 你可以做如下的事情,同时注意我们需要一些辅助函数来管理光标位置。

    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
      };
    }
    #Box {
      width: 400px;
      height: 100px;
      border: 1px solid black;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <div contenteditable="true" id="Box"></div>
    
    <button>Show HTML</button>

    【讨论】:

    • 谢谢。我也会用的。
    猜你喜欢
    • 1970-01-01
    • 2011-12-10
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    相关资源
    最近更新 更多