【分享】微博 @ 符号的用户名提示效果。(想@到谁?)
想@到谁? 至少有3处BUG,建议不要使用这段程序
相信你老早就在腾讯或者新浪的微博上体验到@符号的魅力了
这里有一个简单的实现,浏览器兼容还好。
实现思路
我们可以用onkeyup事件监测文本框是否输入了一个@符号,如果输入了就找到@符号在页面上的绝对位置,弹出选择框。
在操作textarea的时候光标的绝对位置是个麻烦事。
如何获取textarea 里的光标的位置?
请结合图片看下面的实现方法。
A:是一个textarea
B:当前光标位置
首先在页面创建一个(C)具有 visibility:hidden;(占位但是不显示) 属性的DIV。
他的位置、宽度、高度与A文本框一样(这意味着C现在与A已经重叠了)。
然后我们获取到B位置前面的所有文本(“这是一个textarea”),写入C 里面,在追加一个<span id='FFF'></span>;
那么ID为FFF 的span标签的位置就是 B的位置。
这样把获取光标位置转化为获取一个span元素的位置就好办很多了。
简单吧!
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;
} elsereturn 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);
}
}
* 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;
} elsereturn 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();
}
returnfalse;
}
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();
varchar= 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);
}
returntrue;
}
_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){
returnfunction(){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();
returnfalse;
}
return _this;
}
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();
}
returnfalse;
}
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();
varchar= 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);
}
returntrue;
}
_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){
returnfunction(){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();
returnfalse;
}
return _this;
}
作者:idche
原文地址:http://www.cnblogs.com/idche/archive/2010/10/30/1865085.html