新div中的每个单词

时间:2018-07-07 01:15:25

标签: javascript

我想要光标在文本区域中的正常行为,请尝试使用chrome导航器。

我正在使用contenteditable,但它应该像文本区域一样工作, 每个单词都必须在非常必要的范围内,我不想使用纯文本

对于每个空格,每个文字都必须变为div或span, 并且光标应该正常运行

示例:

        "hello word" for the space the result will is 
         <div>hello</div>


         imagine that the second space is after the word "word", 
         for the second space the result will is 
         <div>hello</div><div>word</div>

        and written spacebar before the caracter 'r'
        the result will is <div>hello</div><div>wo</div><div>rd</div>

window.onload = function() {
  document.getElementById('test').addEventListener('keyup', function(e) {
    if (e.which === 32) {
      var parent = document.getElementById("test");
      var range = document.createRange();
      var selection = window.getSelection();
      var number = window.getSelection().anchorNode.parentNode.id;

      convertirEnSpans();
      agregarIds();
      //parent.childNodes[parseInt(number) + 1] el nodo siguiente
      //el cursor debe situarse en el inicio del nodo siguiente
      if (parent.childNodes[parseInt(number) + 1] !== undefined) { //comprobamos que exista el nodo siguiente
        var element = parent.childNodes[parseInt(number) + 1];
        range.setStart(element, 0);
        range.collapse(true);
        selection.removeAllRanges();
        selection.addRange(range);
        element.focus();
      }
    }
  });

  function convertirEnSpans() {
    let text = document.getElementById('test');
    let spans = text.getElementsByTagName('span');
    if (spans.length > 0) {
      text = '';
      for (var i = 0; i < spans.length; i++) {
        text += spans[i].innerHTML + ' ';
      }
      text = text.substring(0, text.length - 1);
    } else {
      text = text.innerHTML;
    }

    var wordsWithSpan = text.split(' ').map(function(c) {
      return '<span class="word">' + c + '</span>';
    }).join('');

    document.getElementById('test').innerHTML = wordsWithSpan;
  }

  function agregarIds() { //agregamos ids para saber en que nodo esta en cursor
    text = document.getElementById('test');
    let nodeSpans = text.getElementsByTagName('span');
    for (var i = 0; i < nodeSpans.length; i++) {
      nodeSpans[i].id = i;
    }
  }
}
.word {
  color: red;
  padding-right: 2px;
}

div {
  border: 1px solid;
  margin: 50px;
}
<div contenteditable="true" id="test">
</div>

我无法使光标正常运行,光标跳到所有部分,如何解决?

我只对使用空格键感兴趣, 不要尝试使用Enter键

使用@DurgeshAhire的答案进行更新
但是在单词中间书写时仍然存在错误

window.onload = function() {
  document.getElementById('test').addEventListener('keyup', function(e) {
    if (e.which === 32) {
      var parent = document.getElementById("test");
      var range = document.createRange();
      var selection = window.getSelection();
      var number = window.getSelection().anchorNode.parentNode.id;

      convertirEnSpans();
      agregarIds();

      //parent.childNodes[parseInt(number) + 1] el nodo siguiente
      //el cursor debe situarse en el inicio del nodo siguiente
      if (parent.childNodes[parseInt(number) + 2] !== undefined) { //comprobamos que exista el nodo siguiente
        var element = parent.childNodes[parseInt(number) + 1];
        range.setStart(element, 0);
        range.collapse(true);
        selection.removeAllRanges();
        selection.addRange(range);
        element.focus();
      } else {
        setEndOfContenteditable(parent);
      }
    }
  });


  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
    }
  }



  function convertirEnSpans() {
    let text = document.getElementById('test');
    let spans = text.getElementsByTagName('span');
    if (spans.length > 0) {
      text = '';
      for (var i = 0; i < spans.length; i++) {
        text += spans[i].innerHTML + ' ';
      }
      text = text.substring(0, text.length - 1);
    } else {
      text = text.innerHTML;
    }

    var wordsWithSpan = text.split(' ').map(function(c) {
      return '<span class="word">' + c + '</span>';
    }).join('');

    document.getElementById('test').innerHTML = wordsWithSpan;
  }

  function agregarIds() { //agregamos ids para saber en que nodo esta en cursor
    text = document.getElementById('test');
    let nodeSpans = text.getElementsByTagName('span');
    for (var i = 0; i < nodeSpans.length; i++) {
      nodeSpans[i].id = i;
    }
  }
}
.word {
  color: red;
  padding-right: 3px;
}

div {
  border: 1px solid;
  margin: 50px;
}
<div contenteditable="true" id="test">
</div>

3 个答案:

答案 0 :(得分:1)

  

我使用的是可编辑内容,但它应该像文本区域一样工作

我认为您不需要维护过多的已编写代码。

想法只是立即将div替换为textarea,并在从用户获得输入后,将其替换为div

您可以参考下面的代码段:

function divClicked() {
    var divHtml = $(this).text();
    var editableText = $("<textarea />");
    editableText.val(divHtml);
    $(this).replaceWith(editableText);
    editableText.focus(); //sets focus to element
      var val = editableText.val(); //store the value of the element
      editableText.val(""); //clear the value of the element
     editableText.val(val);  //set that value back.  
    // setup the blur event for this new textarea
    editableText.blur(editableTextBlurred);
}

function editableTextBlurred() {
    var html = $(this).val();
     var wordsWithSpan = html.split(' ').map(function(c) {
      return '<span class="word">' + c + '</span>';
    }).join(' ');
    
    var viewableText = $("<div>");
    viewableText.html(wordsWithSpan);
    $(this).replaceWith(viewableText);
    // setup the click event for this new div
    viewableText.click(divClicked);
}

$(document).ready(function() {
    $("div").click(divClicked);
});
.word {
  color: red;
  padding-right: 2px;
}



div {
  border: 1px solid;
  margin: 50px;
  width:400px;
}



textarea {
     border: 1px solid;
  margin: 50px;
  width:400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="word" contenteditable="true"></diV>

答案 1 :(得分:0)

请检查更新的代码,然后让我知道

    window.onload = function() {
      document.getElementById('test').addEventListener('keyup', function(e) {
        if (e.which === 32) {
          var parent = document.getElementById("test");
          var range = document.createRange();
          var selection = window.getSelection();
          var number = window.getSelection().anchorNode.parentNode.id;

          convertirEnSpans();
          agregarIds();
          
          
          setEndOfContenteditable(parent);

         
        }
      });

  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
        }
     }

      function convertirEnSpans() {
        let text = document.getElementById('test');
        let spans = text.getElementsByTagName('span');
        if (spans.length > 0) {
          text = '';
          for (var i = 0; i < spans.length; i++) {
            text += spans[i].innerHTML + ' ';
          }
          text = text.substring(0, text.length - 1);
        } else {
          text = text.innerHTML;
        }

        var wordsWithSpan = text.split(' ').map(function(c) {
          return '<span class="word">' + c + '</span>';
        }).join('');

        document.getElementById('test').innerHTML = wordsWithSpan;
      }

      function agregarIds() { //agregamos ids para saber en que nodo esta en cursor
        text = document.getElementById('test');
        let nodeSpans = text.getElementsByTagName('span');
        for (var i = 0; i < nodeSpans.length; i++) {
          nodeSpans[i].id = i;
        }
      }
    }
.word {
  color: red;
  padding-right: 2px;
}

div {
  border: 1px solid;
  margin: 50px;
}
<div contenteditable="true" id="test">
</div>

答案 2 :(得分:0)

此代码使您可以在单词中间输入内容,而不会弄乱插入符号的位置!您甚至可以将文本粘贴到div中,它将立即更新!还支持连续多个空格!选择和删除一系列字符(通过单词切入)也可以!

window.onload = function() {
  document.getElementById('test').addEventListener('keyup', function(e) {
    var parent = document.getElementById("test");
    var range = document.createRange();
    var selection = window.getSelection();
    var number = window.getSelection().anchorNode.parentNode.id;

    let pos = getCaret();

    convertirEnSpans();
    agregarIds();

    setCaret(pos);
  });

  function getCaret() {
    var caretOffset = 0;
    if (window.getSelection) {
      var range = window.getSelection().getRangeAt(0);
      var preCaretRange = range.cloneRange();
      preCaretRange.selectNodeContents(test);
      preCaretRange.setEnd(range.endContainer, range.endOffset);
      return preCaretRange.toString().length;
    }
  }

  function setCaret(offset) {
    let nodeSpans = test.getElementsByTagName('span');
    var temp = 0;
    for (var i = 0; i < nodeSpans.length; i++) {
      let len = (nodeSpans[i].innerText || nodeSpans[i].textContent).length;
      if (temp + len >= offset) {
        var range = document.createRange();
        var sel = window.getSelection();
        range.setStart(nodeSpans[i].childNodes[0], offset - temp);
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
        break;
      }
      else {
        temp += len;
      }
    }
  }

  function convertirEnSpans() {
    let text = test.innerText || test.textContent;
    var wordsWithSpan = text.split(/\s/ugmi).map(function(c) {
      if (c.length > 0) return `<span class="word">${c}</span>`;
      else return c;
    }).join('<span>&nbsp;</span>'); // non-breaking space
    test.innerHTML = wordsWithSpan;
  }

  function agregarIds() { // agregamos ids para saber en que nodo esta en cursor
    let nodeSpans = test.getElementsByClassName('word');
    for (var i = 0; i < nodeSpans.length; i++) {
      nodeSpans[i].id = "word" + i; // ids are not allowed to start with a digit
    }
  }
}
.word {
  color: red;
  border: 1px solid black;
}

div {
  border: 1px solid black;
  margin: 50px;
  padding: 5px;
}
<div contenteditable="true" id="test">
</div>

文字周围有黑色边框,因此您可以轻松查看元素。