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


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
Javascript 相关文章推荐
javascript document.images实例
May 27 Javascript
jquery实现图片按比例缩放示例
Jul 01 Javascript
使用pjax实现无刷新更改页面url
Feb 05 Javascript
javascript基于DOM实现权限选择实例分析
May 14 Javascript
JQuery菜单效果的两个实例讲解(3)
Sep 17 Javascript
JS实时弹出新消息提示框并有提示音响起的实现代码
Apr 20 Javascript
javascript时间戳和日期字符串相互转换代码(超简单)
Jun 22 Javascript
vue2 mint-ui loadmore实现下拉刷新,上拉更多功能
Mar 21 Javascript
对angularJs中$sce服务安全显示html文本的实例
Sep 30 Javascript
超轻量级的js时间库miment使用解析
Aug 02 Javascript
javascript sort()对数组中的元素进行排序详解
Oct 13 Javascript
详解小程序BackgroundAudioManager踩坑之旅
Dec 08 Javascript
js focus不起作用的解决方法(主要是因为dom元素是否加载完成)
Nov 05 #Javascript
细说浏览器特性检测(2)-通用事件检测
Nov 05 #Javascript
需要做特殊处理的DOM元素属性的访问
Nov 05 #Javascript
基于jQuery的仿flash的广告轮播
Nov 05 #Javascript
jquery实现文本框鼠标右击无效以及不能输入的代码
Nov 05 #Javascript
基于jquery的loading效果实现代码
Nov 05 #Javascript
解决jQuery插件tipswindown与hintbox冲突
Nov 05 #Javascript
You might like
基于php设计模式中工厂模式详细介绍
2013/05/15 PHP
thinkPHP实现MemCache分布式缓存功能
2016/03/23 PHP
PHP聊天室简单实现方法详解
2018/12/08 PHP
Laravel框架学习笔记之批量更新数据功能
2019/05/30 PHP
PHP使用观察者模式处理异常信息的方法详解
2019/09/24 PHP
javascript 跳转代码集合
2009/12/03 Javascript
ztree获取当前选中节点子节点id集合的方法
2015/02/12 Javascript
JavaScript中的fontsize()方法使用详解
2015/06/08 Javascript
jquery实现邮箱自动填充提示功能
2015/11/17 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
2016/05/28 Javascript
Bootstrap导航条学习使用(一)
2017/02/08 Javascript
彻底学会Angular.js中的transclusion
2017/03/12 Javascript
ES6 javascript中Class类继承用法实例详解
2017/10/30 Javascript
微信小程序云开发之模拟后台增删改查
2019/05/16 Javascript
js时间转换毫秒的实例代码
2019/08/21 Javascript
vue项目中使用多选框的实例代码
2020/07/22 Javascript
[05:46]DOTA2英雄梦之声_第18期_陈
2014/06/20 DOTA
[01:24]2014DOTA2 TI第二日 YYF表示这届谁赢都有可能
2014/07/11 DOTA
Python常用列表数据结构小结
2014/08/06 Python
python中__call__内置函数用法实例
2015/06/04 Python
python中将函数赋值给变量时需要注意的一些问题
2017/08/18 Python
matplotlib绘制动画代码示例
2018/01/02 Python
python3获取当前文件的上一级目录实例
2018/04/26 Python
Python多进程fork()函数详解
2019/02/22 Python
微信小程序python用户认证的实现
2019/07/29 Python
解决使用export_graphviz可视化树报错的问题
2019/08/09 Python
基于Python+QT的gui程序开发实现
2020/07/03 Python
简单了解Django项目应用创建过程
2020/07/06 Python
python 获取计算机的网卡信息
2021/02/18 Python
css3打造一款漂亮的卡哇伊按钮
2013/03/20 HTML / CSS
加拿大购物频道:The Shopping Channel
2016/07/21 全球购物
瑞士图书网站:Weltbild.ch
2019/09/17 全球购物
企业形象策划方案
2014/05/29 职场文书
婚育证明样本
2015/06/16 职场文书
详解如何使用Node.js实现热重载页面
2021/05/06 Javascript
Java十分钟精通进阶适配器模式
2022/04/06 Java/Android