Posted in Javascript onNovember 05, 2010
在下面的文本框输入“@” 看一下效果吧!
已经解决 IE,FF ,CHORME 主流浏览器的兼容问题。有需要这个JS的朋友可以直接拿去用。
由于我实在无法把这个效果插入到这遍文章里。所以只能让大家下载我演示的文件了。
下载演示文件
思路
我们可以用onkeyup事件监测文本框是否输入了一个@符号,如果输入了,就找到@符号在页面上的绝对位置,弹出提示。(实际制作过程中会遇到各种各样的问题)
问题: textarea 里的光标位置无法直接获取。
所以我们只能迂回前进了。
解决弹出框的位置
首先你是针对网页里面的textarea(这是一个很麻烦的标签) 这个标签的一些操作。
所以关于他的一些API你必须收集到。(下面会有提供)
A:是一个textarea
B:当前光标位置
我们的方案是 首先在页面创建一个(C)具有 visibility:hidden;(占位但是不显示) 属性的DIV。
他的位置,宽度,高度与A文本框一样(这意味着C现在与A已经重叠了)。
然后我们获取到B位置前面的所有文本(可以用js获取到),写入C 里面,在追加一个<span id='FFF'></span>;
那么ID为FFF 的span标签的位置就是 B的位置。
HTML页面会多了一些这样的标签
<div id="c">这你是一个textarea @<span id='FFF'></span><div>
可以获取到@符号的位置,其他问题都只是调试的问题了,就不多说了。你可以直接下载源码
textarea 的一些操作
/* * TT textarea 操作函数 * info(t) 基本信息 * getCursorPosition(t) 光标位置 * setCursorPosition(t, p) 设置光标位置 * add(t,txt) 添加内容到光标处 */ var TT = { info:function(t){ var o = t.getBoundingClientRect(); var w = t.offsetWidth; var h = t.offsetHeight; return {top:o.top, left:o.left, width:w, height:h}; }, getCursorPosition: function(t){ if (document.selection) { t.focus(); var ds = document.selection; var range = null; range = ds.createRange(); var stored_range = range.duplicate(); stored_range.moveToElementText(t); stored_range.setEndPoint("EndToEnd", range); t.selectionStart = stored_range.text.length - range.text.length; t.selectionEnd = t.selectionStart + range.text.length; return t.selectionStart; } else return t.selectionStart }, setCursorPosition:function(t, p){ var n = p == 'end' ? t.value.length : p; if(document.selection){ var range = t.createTextRange(); range.moveEnd('character', -t.value.length); range.moveEnd('character', n); range.moveStart('character', n); range.select(); }else{ t.setSelectionRange(n,n); t.focus(); } }, add:function (t, txt){ var val = t.value; var wrap = wrap || '' ; if(document.selection){ document.selection.createRange().text = txt; } else { var cp = t.selectionStart; var ubbLength = t.value.length; t.value = t.value.slice(0,t.selectionStart) + txt + t.value.slice(t.selectionStart, ubbLength); this.setCursorPosition(t, cp + txt.length); }; }, del:function(t, n){ var p = this.getCursorPosition(t); var s = t.scrollTop; t.value = t.value.slice(0,p - n) + t.value.slice(p); this.setCursorPosition(t ,p - n); D.FF && setTimeout(function(){t.scrollTop = s},10); } }
主要的一些JS
var AutoTips = function(A){ var elem = A.id ? D.$(A.id) : A.elem; var checkLength = 5; var _this = {}; var key = ''; _this.start = function(){ if(!D.$(config.boxID)){ var h = html.slice(); var info = TT.info(elem); var div = D.DC('DIV'); var bs = D.BS(); h = h.replace('$top$',(info.top + bs.top)). replace('$left$',(info.left + bs.left)). replace('$width$',info.width). replace('$height$',info.height). replace('$SCTOP$','0'); div.innerHTML = h; document.body.appendChild(div); }else{ _this.updatePosstion(); } } _this.keyupFn = function(e){ var e = e || window.event; var code = e.keyCode; if(code == 38 || code == 40 || code == 13) { if(code==13 && D.$(config.wrap).style.display != 'none'){ _this.enter(); } return false; } var cp = TT.getCursorPosition(elem); if(!cp) return _this.hide(); var valuep = elem.value.slice(0, cp); var val = valuep.slice(-checkLength); var chars = val.match(/(\w+)?@(\w+)$|@$/); if(chars == null) return _this.hide(); var char = chars[2] ? chars[2] : ''; D.$(config.valuepWrap).innerHTML = valuep.slice(0,valuep.length - char.length).replace(/\n/g,'<br/>'). replace(/\s/g,' ') + config.positionHTML; _this.showList(char); } _this.showList = function(char){ key = char; var data = DS.inquiry(friendsData, char, 5); var html = listHTML.slice(); var h = ''; var len = data.length; if(len == 0){_this.hide();return;} var reg = new RegExp(char); var em = '<em>'+ char +'</em>'; for(var i=0; i<len; i++){ var hm = data[i]['user'].replace(reg,em); h += html.replace(/\$ACCOUNT\$|\$NAME\$/g,data[i]['name']). replace('$SACCOUNT$',hm).replace('$ID$',data[i]['user']); } _this.updatePosstion(); var p = D.$(config.position).getBoundingClientRect(); var bs = D.BS(); var d = D.$(config.wrap).style; d.top = p.top + 20 + bs.top + 'px'; d.left = p.left - 5 + 'px'; D.$(config.listWrap).innerHTML = h; _this.show(); } _this.KeyDown = function(e){ var e = e || window.event; var code = e.keyCode; if(code == 38 || code == 40 || code == 13){ return selectList.selectIndex(code); } return true; } _this.updatePosstion = function(){ var p = TT.info(elem); var bs = D.BS(); var d = D.$(config.boxID).style; d.top = p.top + bs.top +'px'; d.left = p.left + bs.left + 'px'; d.width = p.width+'px'; d.height = p.height+'px'; D.$(config.boxID).scrollTop = elem.scrollTop; } _this.show = function(){ selectList.list = D.$(config.listWrap).getElementsByTagName('li'); selectList.index = -1; selectList._this = _this; _this.cursorSelect(selectList.list); elem.onkeydown = _this.KeyDown; D.$(config.wrap).style.display = 'block'; } _this.cursorSelect = function(list){ for(var i=0; i<list.length; i++){ list[i].onmouseover = (function(i){ return function(){selectList.setSelected(i)}; })(i); list[i].onclick = _this.enter; } } _this.hide = function(){ selectList.list = null; selectList.index = -1; selectList._this = null; D.ER(elem, 'keydown', _this.KeyDown); D.$(config.wrap).style.display = 'none'; } _this.bind = function(){ elem.onkeyup = _this.keyupFn; elem.onclick = _this.keyupFn; elem.onblur = function(){setTimeout(_this.hide, 100)} //elem.onkeyup= fn; //D.EA(elem, 'keyup', _this.keyupFn, false) //D.EA(elem, 'keyup', fn, false) //D.EA(elem, 'click', _this.keyupFn, false); //D.EA(elem, 'blur', function(){setTimeout(_this.hide, 100)}, false); } _this.enter = function(){ TT.del(elem, key.length, key); TT.add(elem, selectList.list[selectList.index].getElementsByTagName('A')[0].rel+' '); _this.hide(); return false; } return _this; }
作者:idche
微博@符号的用户名提示效果。(想@到谁?)
声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@