本文給大家分享的是一則使用javascript完美實現兼容各大浏覽器的@好友自動提示的特效,是根據百度貼吧的效果模仿來的,推薦給小伙伴們,希望大家能夠喜歡。
要求
1.輸入@時,彈出匹配的好友菜單
2.光標進入包含有"@好友"的標簽時,彈出菜單
3.按backspace刪除時,如果光標前面是包含有"@好友"的標簽,彈出菜單
4.兼容ie,firefox.
具體做法
針對要求一,很自然的會想到對輸入框綁定事件。這裡要綁定mousedown,而不是mouseup.因為如果是mouseup的話,用event.preventDefault()是無法阻止鍵盤輸入@的。另外,這裡在事件回調中用return false也是起不了作用的。
綁定mousedown事件後,就要插入自定義的包含有"@好友"的標簽了。新浪微博的輸入框是用textarea做的,無法知道其內部是怎樣處理的,只好看百度貼吧了。
可以看到,貼吧是插入了<span class='at'></span>標簽。這應該是方便後台用正則表達式匹配。
具體的
代碼如下:
vm.check_key=function(e){
var editor=$('editor'),range;
if(e.shiftKey&&e.keyCode==50){
if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.pasteHTML(" <span id='at"+at_index+"' class='at_span'>@</span> ");
}else{
document.execCommand("insertHtml", false," <span id='at"+at_index+"' class='at_span'>@</span> ");
}
e.preventDefault();
}
};
這裡需要在光標處插入,所以用到了range.
然後就是菜單顯示了,關鍵在於怎麼定位。我的做法很垃圾,就是為插入的span添加id,然後根據span id的位置為菜單定位。如果有更好的做法,請告訴我一聲。
具體的
代碼如下:
function at_box_show(at){
var at_pos=avalon($(at)).position();
$('at_box').style.left=at_pos.left+'px';
$('at_box').style.top=at_pos.top+16+'px';
$('at_box').style.display='block';
}
var at_index=0,cur_index=0;
avalon.define('editor', function(vm) {
vm.item_click=function(){
$('at'+cur_index).innerHTML="@"+this.innerHTML;
$('at_box').style.display='none';
at_index++;
};
vm.check_key=function(e){
var editor=$('editor'),a=getCharacterPrecedingCaret(editor),range;
if(e.shiftKey&&e.keyCode==50){
if (document.selection && document.selection.createRange) {
range = document.selection.createRange();
range.pasteHTML(" <span id='at"+at_index+"' class='at_span'>@</span> ");
}else{
document.execCommand("insertHtml", false," <span id='at"+at_index+"' class='at_span'>@</span> ");
}
at_box_show('at'+at_index);
cur_index=at_index;
e.preventDefault();
}
};
});
at_show_box根據新插入的span id,為at_box定位,然後顯示菜單。cur_index表示光標當前所在的span id.設置這個變量因為用戶可能倒回去改已經插入的span,而at_index是一直遞增的,所以這裡就還需要一個變量。
用戶點擊菜單中好友項,觸發item_click回調。回調裡就是將好友名字用innserHTML添加到當前span裡面.然後隱藏菜單,at_index++。
上面是監聽shift+@,接著是監聽backspace刪除。
代碼如下:
function getTextBeforeCursor(containerEl) {
var precedingChar = "", sel, range, precedingRange;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount > 0) {
range = sel.getRangeAt(0).cloneRange();
range.collapse(true);
range.setStart(containerEl, 0);
precedingChar = range.cloneContents();
}
} else if ( (sel = document.selection)) {
range = sel.createRange();
precedingRange = range.duplicate();
precedingRange.moveToElementText(containerEl);
precedingRange.setEndPoint("EndToStart", range);
precedingChar = precedingRange.htmlText;
}
return precedingChar;
}
getTextBeforeCursor的作用是獲取光標前的內容.由於兼容性,這個函數在標准浏覽器中可以得到是光標前所有內容的DocumentFragment,而在ie中就只能得到文本(不是node)了,不過這個html字符串可以轉換成DocumentFragment.在avalon中用parseHTML就可以將html字符串變成node了。jquery中用$(html)[0]也能得到node.
有了這個函數,再用lastChild就可以判斷光標是不是在光標前html的lastChild裡,並且這個lastChild是span。
具體的
代碼如下:
var a=getTextBeforeCursor($('editor'));
if(e.keyCode==8){
if(!-[1,]){
var b=avalon.parseHTML(a).lastChild;
}else{
var b=a.lastChild;
}
if(b.nodeType==1&&b.nodeName=='SPAN'){
var id=b.id;
cur_index=b.id.substring(2);
at_box_show(b.id);
}else
$('at_box').style.display='none';
}
最後是光標進入span標簽,顯示菜單。這個很顯然需要綁定鼠標事件。這裡綁定mouseup,因為如果綁定mousedown的話,需要鼠標在span標簽再點一次才能顯示菜單。至於原理,和上面差不多。
代碼如下:
vm.check_mouse=function(e){
var editor=$('editor'),a=getTextBeforeCursor(editor);
if(!-[1,]){
var b=avalon.parseHTML(getTextBeforeCursor(editor)).lastChild;
}else{
var b=a.lastChild;
}
if(b!=null&&b.nodeType==1&&b.nodeName=='SPAN'){
var id=b.id;
cur_index=b.id.substring(2);
at_box_show(b.id);
}else
$('at_box').style.display='none';
};
注意,如果光標在span裡面,就要取出它的id,at_box根據這個id定位,另外還要重置cur_index.
至於ajax更新菜單,字符匹配我就不做了
效果
firefox
ie8
ie7
ie6
下載
以上就是本文所述的全部內容了,希望對大家了解javascript能夠有所幫助。