【分享】微博 @ 符号的用户名提示效果。(想@到谁?)

想@到谁?   至少有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;
}
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, ' &nbsp; ' ) + 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

原文地址:http://www.cnblogs.com/idche/archive/2010/10/30/1865085.html

 

你可能感兴趣的:(用户)