仿微信、qq聊天,@好友功能
文章主要介绍我们平时用的qq,微信输入框里面的@功能
如图,输入@符号 会出现一个ul ul的位置随着@符号的位置变动
下面是代码 希望对大家有用 直接全部复制,在编辑器中打开 即可
<!DOCTYPE html> <html> <head> <title>聊天</title> <style> body, html { padding: 0; margin: 0; } .count{ background-color: pink; } </style> </head> <body> <textarea id="text" onkeyup="show(this)" style="width: 340px; height: 210px;"></textarea> <br /> <div id="show" style=" position: absolute;border:1px solid grey;font-size:13px; display:none;"> <ul id="ul1" style="width:100px;padding: 0 ;list-style:none;"> <li >1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li class="count">6</li> </ul> </div> </body> </html> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript"> function show(elem) { var p = kingwolfofsky.getInputPositon(elem); var s = document.getElementById('show'); var len = $('#text').val() var lengths=len.slice(0, document.getElementById('text').selectionStart) //光标位置 if (lengths.charAt(lengths.length-1)=='@') { s.style.display = 'block'; s.style.top = p.bottom + 'px'; s.style.left = p.left + 'px'; $("ul li:last-child").addClass("count").siblings().removeClass('count'); return }else{ s.style.display = 'none'; return } if ($('#text').val().indexOf('@') > -1 && document.getElementById('text').selectionStart == $('#text').val().length) { s.style.display = 'block'; s.style.top = p.bottom + 'px'; s.style.left = p.left + 'px'; $("ul li:last-child").addClass("count").siblings().removeClass('count'); } else { s.style.display = 'none'; return } } var kingwolfofsky = { /** * 获取输入光标在页面中的坐标 * @param {HTMLElement} 输入框元素 * @return {Object} 返回left和top,bottom */ getInputPositon: function (elem) { if (document.selection) { //IE Support elem.focus(); var Sel = document.selection.createRange(); return { left: Sel.boundingLeft, top: Sel.boundingTop, bottom: Sel.boundingTop + Sel.boundingHeight }; } else { var that = this; var cloneDiv = '{$clone_div}', cloneLeft = '{$cloneLeft}', cloneFocus = '{$cloneFocus}', cloneRight = '{$cloneRight}'; var none = '<span style="white-space:pre-wrap;"> </span>'; var div = elem[cloneDiv] || document.createElement('div'), focus = elem[cloneFocus] || document.createElement('span'); var text = elem[cloneLeft] || document.createElement('span'); var offset = that._offset(elem), index = this._getFocus(elem), focusOffset = { left: 0, top: 0 }; if (!elem[cloneDiv]) { elem[cloneDiv] = div, elem[cloneFocus] = focus; elem[cloneLeft] = text; div.appendChild(text); div.appendChild(focus); document.body.appendChild(div); focus.innerHTML = '|'; focus.style.cssText = 'display:inline-block;width:0px;overflow:hidden;z-index:-100;word-wrap:break-word;word-break:break-all;'; div.className = this._cloneStyle(elem); div.style.cssText = 'visibility:hidden;display:inline-block;position:absolute;z-index:-100;word-wrap:break-word;word-break:break-all;overflow:hidden;'; }; div.style.left = this._offset(elem).left + "px"; div.style.top = this._offset(elem).top + "px"; var strTmp = elem.value.substring(0, index).replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br/>').replace(/\s/g, none); text.innerHTML = strTmp; focus.style.display = 'inline-block'; try { focusOffset = this._offset(focus); } catch (e) { }; focus.style.display = 'none'; return { left: focusOffset.left, top: focusOffset.top, bottom: focusOffset.bottom }; } }, // 克隆元素样式并返回类 _cloneStyle: function (elem, cache) { if (!cache && elem['${cloneName}']) return elem['${cloneName}']; var className, name, rstyle = /^(number|string)$/; var rname = /^(content|outline|outlineWidth)$/; //Opera: content; IE8:outline && outlineWidth var cssText = [], sStyle = elem.style; for (name in sStyle) { if (!rname.test(name)) { val = this._getStyle(elem, name); if (val !== '' && rstyle.test(typeof val)) { // Firefox 4 name = name.replace(/([A-Z])/g, "-$1").toLowerCase(); cssText.push(name); cssText.push(':'); cssText.push(val); cssText.push(';'); }; }; }; cssText = cssText.join(''); elem['${cloneName}'] = className = 'clone' + (new Date).getTime(); this._addHeadStyle('.' + className + '{' + cssText + '}'); return className; }, // 向页头插入样式 _addHeadStyle: function (content) { var style = this._style[document]; if (!style) { style = this._style[document] = document.createElement('style'); document.getElementsByTagName('head')[0].appendChild(style); }; style.styleSheet && (style.styleSheet.cssText += content) || style.appendChild(document.createTextNode(content)); }, _style: {}, // 获取最终样式 _getStyle: 'getComputedStyle' in window ? function (elem, name) { return getComputedStyle(elem, null)[name]; } : function (elem, name) { return elem.currentStyle[name]; }, // 获取光标在文本框的位置 _getFocus: function (elem) { var index = 0; if (document.selection) {// IE Support elem.focus(); var Sel = document.selection.createRange(); if (elem.nodeName === 'TEXTAREA') {//textarea var Sel2 = Sel.duplicate(); Sel2.moveToElementText(elem); var index = -1; while (Sel2.inRange(Sel)) { Sel2.moveStart('character'); index++; }; } else if (elem.nodeName === 'INPUT') {// input Sel.moveStart('character', -elem.value.length); index = Sel.text.length; } } else if (elem.selectionStart || elem.selectionStart == '0') { // Firefox support index = elem.selectionStart; } return (index); }, // 获取元素在页面中位置 _offset: function (elem) { var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement; var clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0; var top = box.top + (self.pageYOffset || docElem.scrollTop) - clientTop, left = box.left + (self.pageXOffset || docElem.scrollLeft) - clientLeft; return { left: left, top: top, right: left + box.width, bottom: top + box.height }; } }; //$(".text")为要插入的文本框 //insertContent("( )")括号内为要插入的内容 (function ($) { $.fn.extend({ insertContent: function (myValue, t) { var $t = $(this)[0]; if (document.selection) { // ie this.focus(); var sel = document.selection.createRange(); sel.text = myValue; this.focus(); sel.moveStart('character', -l); var wee = sel.text.length; if (arguments.length == 2) { var l = $t.value.length; sel.moveEnd("character", wee + t); t <= 0 ? sel.moveStart("character", wee - 2 * t - myValue.length) : sel.moveStart( "character", wee - t - myValue.length); sel.select(); } } else if ($t.selectionStart || $t.selectionStart == '0') { var startPos = $t.selectionStart; var endPos = $t.selectionEnd; var scrollTop = $t.scrollTop; $t.value = $t.value.substring(0, startPos) + myValue + $t.value.substring(endPos, $t.value.length); this.focus(); $t.selectionStart = startPos + myValue.length; $t.selectionEnd = startPos + myValue.length; $t.scrollTop = scrollTop; if (arguments.length == 2) { $t.setSelectionRange(startPos - t, $t.selectionEnd + t); this.focus(); } } else { this.value += myValue; this.focus(); } } }) })(jQuery); //点击选中事件 $('li').on('click',function(e){ e.stopPropagation() var target = e.target || e.srcElement; var content = target.innerHTML $("#text").insertContent(content); document.getElementById('show').style.display = 'none'; }).on('mouseover',function(e){ $(this).addClass("count").siblings().removeClass('count'); }) //点击输入框让ul消失 $("#text").on('click',function(e){ document.getElementById('show').style.display = 'none'; }) </script>