添加表情符号后,jQuery焦点光标

时间:2019-03-18 06:31:24

标签: javascript jquery html css

我正在尝试在contenteditable div中添加一个简单的添加表情符号。但是添加表情符号光标后出现问题。我已经从codepen.io创建了这个 DEMO 。在此演示中,您可以看到树示例表情符号。当您单击第一个表情符号时,表情符号将添加到#text内容可编辑div中。到目前为止,一切都还不错,但是在添加表情符号之后,它仍然位于光标表情符号的后面。

添加表情符号后,我希望您在光标表情符号的前面。我怎样才能做到这一点 ?有人可以在这里帮助我吗?

$(document).ready(function() {
  $("body").on("paste", "#text", function(e) {
    e.preventDefault();
  });
  $("body").on("keydown", "#text", function(event) {
    //$('.character').text($(this).text().length);
    if ($(this).text().length === 200 && event.keyCode != 8) {
      event.preventDefault();
    }
  });
  // Click to show clicked smiley
  $("body").on("click",".emoji-box", function(){
      var emojiKey = $(this).attr("data-smiley");
      var emojiURL = $(this).attr("data-url"); 
      $("#text").append("<img src="+emojiURL+" class='app-moji'>"); 
      $("#text").focus();
  });
});
html, body {
    width: 100%;
    height: 100%;
    padding: 0px;
    margin: 0px;
    font-family: 'Helvetica Neue', helvetica, arial, sans-serif;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    -ms-text-size-adjust: 100%;
    -webkit-texts-size-adjust: 100%;
    -webkit-backface-visibility: hidden;
}
.container {
  position:relative;
  width:100%;
  max-width:500px;
  margin:0px auto;
  padding-top:100px;
}
.input {
  position:relative;
  width:100%;
  display:inline-block;
  padding:5px 0px;
}
#text {
  width:100%;
  outline:none;
  border:1px solid #d8dbdf;
  padding:15px;
  border-radius:3px;
  -webkit-border-radius:3px;
  font-weight:300;
  font-size:14px;
  color:#444;  
  line-height: 17px;
  word-wrap: break-word; 
  text-align: left !important;
   
}
#text img { 
  width:25px;
  height:25px;
  vertical-align: middle; 
}
.app-moji {
  margin-left:5px;
  margin-right:5px;
  display: inline-block;
}
[contenteditable=true]:empty:before {
  content: attr(placeholder);
  display: block; /* For Firefox */
  color:#d8dbdf;
}
.button {
  float:right;
  width:100px;
  padding:8px;
  text-align:center;
  background-color:#d8dbdf;
  border-raduis:3px;
  -webkit-border-radius:3px;
  cursor:pointer;
   transition: background-color 1s linear;
    -moz-transition: background-color 1s linear;
    -o-transition: background-color 1s linear;
    -webkit-transition: background-color 1s linear;
}
.button:hover {
  background-color:#000;
  color:#fff;
     
}
div.coloranimation {
  transition: background-color 1s linear;
    -moz-transition: background-color 1s linear;
    -o-transition: background-color 1s linear;
    -webkit-transition: background-color 1s linear;
  background-color:#000000;
}

.ornekgoster {
  position:relative;
  width:100%;
  padding:10px;
}
.ornek {
  position:relative;
  width:100%;
  font-weight:300;
  font-size:13px;
  color:#444;
} 

*{
  box-sizing:border-box;
  -webkit-box-sizing:border-box;
}

.ap-emoji {
  position: relative;
  float: left;
  width: 100%;
  padding-right: 10px;
   overflow:hidden;
 margin-top:20px;
}

.emoji-box {
   position:relative;
   width:29px;
   height:29px;
   float:left;  
   padding:2px;
   cursor:pointer;
}
.emoji-box img {
   width:100%;
   position:relative;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="input">
    <div id="text" placeholder="Wite something..." contenteditable="true"></div>
    <input type="hidden" id="hidden" value=""/>
  </div> 
  
  <div class="ap-emoji" id="emoji1">
    <div class="emoji-box" data-smiley=":P" data-url="https://cdn.shopify.com/s/files/1/1061/1924/products/Hungry_Emoji_Icon_c20f1808-f3e2-4051-8941-3d157764e8cb.png"><img src="https://cdn.shopify.com/s/files/1/1061/1924/products/Hungry_Emoji_Icon_c20f1808-f3e2-4051-8941-3d157764e8cb.png"></div>
     <div class="emoji-box" data-smiley=":D" data-url="http://www.bigmouthdesign.co.uk/wp-content/uploads/2017/08/Happy-Face.png"><img src="http://www.bigmouthdesign.co.uk/wp-content/uploads/2017/08/Happy-Face.png"></div>
     <div class="emoji-box" data-smiley="<3" data-url="http://clipart.info/images/ccovers/1496184263Heart-Eyes-Emoji-png-transparent-2.png"><img src="http://clipart.info/images/ccovers/1496184263Heart-Eyes-Emoji-png-transparent-2.png"></div>
    </div>
</div>

3 个答案:

答案 0 :(得分:2)

如下使用Selection对象

$(document).ready(function() {
  $("body").on("paste", "#text", function(e) {
    e.preventDefault();
  });
  $("body").on("keydown", "#text", function(event) {
    //$('.character').text($(this).text().length);
    if ($(this).text().length === 200 && event.keyCode != 8) {
      event.preventDefault();
    }
  });
  // Click to show clicked smiley
  $("body").on("click", ".emoji-box", function() {
    var emojiKey = $(this).attr("data-smiley");
    var emojiURL = $(this).attr("data-url");
    $("#text").append("<img src=" + emojiURL + " class='app-moji'>");
    $("#text").focus();
    var el = document.getElementById("text");
    placeCaretAtEnd(el);

  });
});

function placeCaretAtEnd(el) {
  el.focus();
  if (typeof window.getSelection != "undefined" &&
    typeof document.createRange != "undefined") {
    var range = document.createRange();
    range.selectNodeContents(el);
    range.collapse(false);
    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
  } else if (typeof document.body.createTextRange != "undefined") {
    var textRange = document.body.createTextRange();
    textRange.moveToElementText(el);
    textRange.collapse(false);
    textRange.select();
  }
}
html,
body {
  width: 100%;
  height: 100%;
  padding: 0px;
  margin: 0px;
  font-family: 'Helvetica Neue', helvetica, arial, sans-serif;
  -moz-osx-font-smoothing: grayscale;
  -webkit-font-smoothing: antialiased;
  -ms-text-size-adjust: 100%;
  -webkit-texts-size-adjust: 100%;
  -webkit-backface-visibility: hidden;
}

.container {
  position: relative;
  width: 100%;
  max-width: 500px;
  margin: 0px auto;
  padding-top: 100px;
}

.input {
  position: relative;
  width: 100%;
  display: inline-block;
  padding: 5px 0px;
}

#text {
  width: 100%;
  outline: none;
  border: 1px solid #d8dbdf;
  padding: 15px;
  border-radius: 3px;
  -webkit-border-radius: 3px;
  font-weight: 300;
  font-size: 14px;
  color: #444;
  line-height: 17px;
  word-wrap: break-word;
  text-align: left !important;
}

#text img {
  width: 25px;
  height: 25px;
  vertical-align: middle;
}

.app-moji {
  margin-left: 5px;
  margin-right: 5px;
  display: inline-block;
}

[contenteditable=true]:empty:before {
  content: attr(placeholder);
  display: block;
  /* For Firefox */
  color: #d8dbdf;
}

.button {
  float: right;
  width: 100px;
  padding: 8px;
  text-align: center;
  background-color: #d8dbdf;
  border-raduis: 3px;
  -webkit-border-radius: 3px;
  cursor: pointer;
  transition: background-color 1s linear;
  -moz-transition: background-color 1s linear;
  -o-transition: background-color 1s linear;
  -webkit-transition: background-color 1s linear;
}

.button:hover {
  background-color: #000;
  color: #fff;
}

div.coloranimation {
  transition: background-color 1s linear;
  -moz-transition: background-color 1s linear;
  -o-transition: background-color 1s linear;
  -webkit-transition: background-color 1s linear;
  background-color: #000000;
}

.ornekgoster {
  position: relative;
  width: 100%;
  padding: 10px;
}

.ornek {
  position: relative;
  width: 100%;
  font-weight: 300;
  font-size: 13px;
  color: #444;
}

* {
  box-sizing: border-box;
  -webkit-box-sizing: border-box;
}

.ap-emoji {
  position: relative;
  float: left;
  width: 100%;
  padding-right: 10px;
  overflow: hidden;
  margin-top: 20px;
}

.emoji-box {
  position: relative;
  width: 29px;
  height: 29px;
  float: left;
  padding: 2px;
  cursor: pointer;
}

.emoji-box img {
  width: 100%;
  position: relative;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="input">
    <div id="text" placeholder="Wite something..." contenteditable="true"></div>
    <input type="hidden" id="hidden" value="" id="txt" />
  </div>

  <div class="ap-emoji" id="emoji1">
    <div class="emoji-box" data-smiley=":P" data-url="https://cdn.shopify.com/s/files/1/1061/1924/products/Hungry_Emoji_Icon_c20f1808-f3e2-4051-8941-3d157764e8cb.png"><img src="https://cdn.shopify.com/s/files/1/1061/1924/products/Hungry_Emoji_Icon_c20f1808-f3e2-4051-8941-3d157764e8cb.png"></div>
    <div class="emoji-box" data-smiley=":D" data-url="http://www.bigmouthdesign.co.uk/wp-content/uploads/2017/08/Happy-Face.png"><img src="http://www.bigmouthdesign.co.uk/wp-content/uploads/2017/08/Happy-Face.png"></div>
    <div class="emoji-box" data-smiley="<3" data-url="http://clipart.info/images/ccovers/1496184263Heart-Eyes-Emoji-png-transparent-2.png"><img src="http://clipart.info/images/ccovers/1496184263Heart-Eyes-Emoji-png-transparent-2.png"></div>
  </div>
</div>

答案 1 :(得分:1)

实际上,您想要的是更新的插入符位置帖子插入/删除。 您还必须考虑到用户自己可以在插入的表情符号之间的任意位置更新插入符号的位置。 更好的解决方案是在给定的插入位置插入HTML

如果您粘贴HTML内容,这也适用。只需从主体上的粘贴侦听器中删除您的 event.preventDefault()

对于contentEditable代码,您应该参考stackoverflow上TimDown给出的解决方案。他是一些评价最高的解决方案。 ContentEditable容易变得复杂。我相信您的要求不会在这里结束。 如果可能,请尝试使用优质的标准库,这样可以节省大量时间和精力。

请参阅下面的代码段,希望对您有所帮助。

$(document).ready(function() {
  $("body").on("paste", "#text", function(e) {
    e.preventDefault();
  });
  $("body").on("keydown", "#text", function(event) {
    //$('.character').text($(this).text().length);
    if ($(this).text().length === 200 && event.keyCode != 8) {
      event.preventDefault();
    }
  });
  // Click to show clicked smiley
  $("body").on("click",".emoji-box", function(){
      var emojiKey = $(this).attr("data-smiley");
      var emojiURL = $(this).attr("data-url"); 
      //$("#text").append("<img src="+emojiURL+" class='app-moji'>"); 
      //$("#text").focus();
      insertHTMLAtCaret("<img src="+emojiURL+" class='app-moji'>")
  });
  
  function insertHTMLAtCaret(html) {
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();

            // Range.createContextualFragment() would be useful here but is
            // non-standard and not supported in all browsers (IE9, for one)
            var el = document.createElement("div");
            el.innerHTML = html;
            var frag = document.createDocumentFragment(), node, lastNode;
            while ( (node = el.firstChild) ) {
                lastNode = frag.appendChild(node);
            }
            range.insertNode(frag);
            
            // Preserve the selection
            if (lastNode) {
                range = range.cloneRange();
                range.setStartAfter(lastNode);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if (document.selection && document.selection.type != "Control") {
        // IE < 9
        document.selection.createRange().pasteHTML(html);
    }
  }
});
html, body {
    width: 100%;
    height: 100%;
    padding: 0px;
    margin: 0px;
    font-family: 'Helvetica Neue', helvetica, arial, sans-serif;
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    -ms-text-size-adjust: 100%;
    -webkit-texts-size-adjust: 100%;
    -webkit-backface-visibility: hidden;
}
.container {
  position:relative;
  width:100%;
  max-width:500px;
  margin:0px auto;
  padding-top:100px;
}
.input {
  position:relative;
  width:100%;
  display:inline-block;
  padding:5px 0px;
}
#text {
  width:100%;
  outline:none;
  border:1px solid #d8dbdf;
  padding:15px;
  border-radius:3px;
  -webkit-border-radius:3px;
  font-weight:300;
  font-size:14px;
  color:#444;  
  line-height: 17px;
  word-wrap: break-word; 
  text-align: left !important;
   
}
#text img { 
  width:25px;
  height:25px;
  vertical-align: middle; 
}
.app-moji {
  margin-left:5px;
  margin-right:5px;
  display: inline-block;
}
[contenteditable=true]:empty:before {
  content: attr(placeholder);
  display: block; /* For Firefox */
  color:#d8dbdf;
}
.button {
  float:right;
  width:100px;
  padding:8px;
  text-align:center;
  background-color:#d8dbdf;
  border-raduis:3px;
  -webkit-border-radius:3px;
  cursor:pointer;
   transition: background-color 1s linear;
    -moz-transition: background-color 1s linear;
    -o-transition: background-color 1s linear;
    -webkit-transition: background-color 1s linear;
}
.button:hover {
  background-color:#000;
  color:#fff;
     
}
div.coloranimation {
  transition: background-color 1s linear;
    -moz-transition: background-color 1s linear;
    -o-transition: background-color 1s linear;
    -webkit-transition: background-color 1s linear;
  background-color:#000000;
}

.ornekgoster {
  position:relative;
  width:100%;
  padding:10px;
}
.ornek {
  position:relative;
  width:100%;
  font-weight:300;
  font-size:13px;
  color:#444;
} 

*{
  box-sizing:border-box;
  -webkit-box-sizing:border-box;
}

.ap-emoji {
  position: relative;
  float: left;
  width: 100%;
  padding-right: 10px;
   overflow:hidden;
 margin-top:20px;
}

.emoji-box {
   position:relative;
   width:29px;
   height:29px;
   float:left;  
   padding:2px;
   cursor:pointer;
}
.emoji-box img {
   width:100%;
   position:relative;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="input">
    <div id="text" placeholder="Wite something..." contenteditable="true"></div>
    <input type="hidden" id="hidden" value=""/>
  </div> 
  
  <div class="ap-emoji" id="emoji1">
    <div class="emoji-box" data-smiley=":P" data-url="https://cdn.shopify.com/s/files/1/1061/1924/products/Hungry_Emoji_Icon_c20f1808-f3e2-4051-8941-3d157764e8cb.png"><img src="https://cdn.shopify.com/s/files/1/1061/1924/products/Hungry_Emoji_Icon_c20f1808-f3e2-4051-8941-3d157764e8cb.png"></div>
     <div class="emoji-box" data-smiley=":D" data-url="http://www.bigmouthdesign.co.uk/wp-content/uploads/2017/08/Happy-Face.png"><img src="http://www.bigmouthdesign.co.uk/wp-content/uploads/2017/08/Happy-Face.png"></div>
     <div class="emoji-box" data-smiley="<3" data-url="http://clipart.info/images/ccovers/1496184263Heart-Eyes-Emoji-png-transparent-2.png"><img src="http://clipart.info/images/ccovers/1496184263Heart-Eyes-Emoji-png-transparent-2.png"></div>
    </div>
</div>

答案 2 :(得分:0)

execCommand()

对于易于绑定到按钮并定位插入符号位置或选定区域的文本编辑器功能,请使用execCommand()

以下演示:

回调函数可以插入插入符号或用一些选定的表情符号,粗体和斜体文本覆盖选定区域。表情符号Unicode为十进制格式:

  

&# 代码 ;

此格式将直接呈现为HTML。有关更多表情符号,请参阅amp-what.com


演示

const edit = document.forms.editor;

const editText = event => {
  const evt = event.type;
  const tgt = event.target;
  const cur = event.currentTarget;
  const ui = cur.elements;

  if (evt === 'click') {
    switch (tgt.id) {
      case 'emoji':
        let icon = ui.picto.value;
        document.execCommand('insertHTML', false, icon);
        break;
      case 'bold':
        document.execCommand('bold', false, null);
        break;
      case 'italic':
        document.execCommand('italic', false, null);
        break;
      default:
        break;
    }
  }
};

edit.onclick = editText;
button,
select {
  display: inline-block;
  font: inherit;
  width: 5ch;
  height: 3ex;
  cursor: pointer;
  text-align: center;
  padding: 0 5px;
  line-height: 3ex;
  vertical-align: middle;
}

select {
  width: 6ch;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8'>
  <style>
    html,
    body {
      font: 400 16px/1.3 Helvetica, sans-serif;
      color: #333;
    }
    
    #text {
      outline: none;
      margin: 10px;
      min-height: 200px;
    }
  </style>
</head>

<body>
  <form id='editor'>
    <fieldset id="text" contentEditable="true"></fieldset>
    <fieldset id='panel'>
      <button id='bold'><b>B</b></button>
      <button id='italic'><i>I</i></button>
      <select id='picto'>
        <option value='&#11088;'>&#11088;</option>
        <option value='&#127921;'>&#127921;</option>
        <option value='&#128128;'>&#128128;</option>
        <option value='&#128163;'>&#128163;</option>
        <option value='&#129302;'>&#129302;</option>
      </select>
      <button id='emoji' type='button'>&#11088;</button>
    </fieldset>
  </form>
  <script>
    <!--JavaScript goes here-->
  </script>
</body>

</html>